mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
Better diagnostics [#METR-19808].
This commit is contained in:
parent
4b1c11288a
commit
36e4bcc125
@ -271,7 +271,8 @@ private:
|
|||||||
* Установить has_aggregation = true, если есть GROUP BY или хотя бы одна агрегатная функция.
|
* Установить has_aggregation = true, если есть GROUP BY или хотя бы одна агрегатная функция.
|
||||||
*/
|
*/
|
||||||
void analyzeAggregation();
|
void analyzeAggregation();
|
||||||
void getAggregates(ASTPtr ast, ExpressionActionsPtr & actions);
|
void getAggregates(const ASTPtr & ast, ExpressionActionsPtr & actions);
|
||||||
|
void assertNoAggregates(const ASTPtr & ast, const char * description);
|
||||||
|
|
||||||
/** Получить множество нужных столбцов для чтения из таблицы.
|
/** Получить множество нужных столбцов для чтения из таблицы.
|
||||||
* При этом, столбцы, указанные в ignored_names, считаются ненужными. И параметр ignored_names может модифицироваться.
|
* При этом, столбцы, указанные в ignored_names, считаются ненужными. И параметр ignored_names может модифицироваться.
|
||||||
|
@ -68,6 +68,7 @@ namespace ErrorCodes
|
|||||||
extern const int PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS;
|
extern const int PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS;
|
||||||
extern const int DUPLICATE_COLUMN;
|
extern const int DUPLICATE_COLUMN;
|
||||||
extern const int FUNCTION_CANNOT_HAVE_PARAMETERS;
|
extern const int FUNCTION_CANNOT_HAVE_PARAMETERS;
|
||||||
|
extern const int ILLEGAL_AGGREGATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ bool functionIsInOrGlobalInOperator(const String & name)
|
|||||||
|
|
||||||
void ExpressionAnalyzer::init()
|
void ExpressionAnalyzer::init()
|
||||||
{
|
{
|
||||||
select_query = typeid_cast<ASTSelectQuery *>(&*ast);
|
select_query = typeid_cast<ASTSelectQuery *>(ast.get());
|
||||||
|
|
||||||
/// В зависимости от профиля пользователя проверить наличие прав на выполнение
|
/// В зависимости от профиля пользователя проверить наличие прав на выполнение
|
||||||
/// распределённых подзапросов внутри секций IN или JOIN и обработать эти подзапросы.
|
/// распределённых подзапросов внутри секций IN или JOIN и обработать эти подзапросы.
|
||||||
@ -292,18 +293,18 @@ void ExpressionAnalyzer::initGlobalSubqueries(ASTPtr & ast)
|
|||||||
/// Рекурсивные вызовы. Не опускаемся в подзапросы.
|
/// Рекурсивные вызовы. Не опускаемся в подзапросы.
|
||||||
|
|
||||||
for (auto & child : ast->children)
|
for (auto & child : ast->children)
|
||||||
if (!typeid_cast<ASTSelectQuery *>(&*child))
|
if (!typeid_cast<ASTSelectQuery *>(child.get()))
|
||||||
initGlobalSubqueries(child);
|
initGlobalSubqueries(child);
|
||||||
|
|
||||||
/// Действия, выполняемые снизу вверх.
|
/// Действия, выполняемые снизу вверх.
|
||||||
|
|
||||||
if (ASTFunction * node = typeid_cast<ASTFunction *>(&*ast))
|
if (ASTFunction * node = typeid_cast<ASTFunction *>(ast.get()))
|
||||||
{
|
{
|
||||||
/// Для GLOBAL IN.
|
/// Для GLOBAL IN.
|
||||||
if (do_global && (node->name == "globalIn" || node->name == "globalNotIn"))
|
if (do_global && (node->name == "globalIn" || node->name == "globalNotIn"))
|
||||||
addExternalStorage(node->arguments->children.at(1));
|
addExternalStorage(node->arguments->children.at(1));
|
||||||
}
|
}
|
||||||
else if (ASTJoin * node = typeid_cast<ASTJoin *>(&*ast))
|
else if (ASTJoin * node = typeid_cast<ASTJoin *>(ast.get()))
|
||||||
{
|
{
|
||||||
/// Для GLOBAL JOIN.
|
/// Для GLOBAL JOIN.
|
||||||
if (do_global && node->locality == ASTJoin::Global)
|
if (do_global && node->locality == ASTJoin::Global)
|
||||||
@ -321,7 +322,7 @@ void ExpressionAnalyzer::findExternalTables(ASTPtr & ast)
|
|||||||
/// Если идентификатор типа таблица
|
/// Если идентификатор типа таблица
|
||||||
StoragePtr external_storage;
|
StoragePtr external_storage;
|
||||||
|
|
||||||
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(ast.get()))
|
||||||
if (node->kind == ASTIdentifier::Table)
|
if (node->kind == ASTIdentifier::Table)
|
||||||
if ((external_storage = context.tryGetExternalTable(node->name)))
|
if ((external_storage = context.tryGetExternalTable(node->name)))
|
||||||
external_tables[node->name] = external_storage;
|
external_tables[node->name] = external_storage;
|
||||||
@ -338,7 +339,7 @@ void ExpressionAnalyzer::addExternalStorage(ASTPtr & subquery_or_table_name)
|
|||||||
if (!(storage && storage->isRemote()))
|
if (!(storage && storage->isRemote()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (const ASTIdentifier * table = typeid_cast<const ASTIdentifier *>(&*subquery_or_table_name))
|
if (const ASTIdentifier * table = typeid_cast<const ASTIdentifier *>(subquery_or_table_name.get()))
|
||||||
{
|
{
|
||||||
/// Если это уже внешняя таблица, ничего заполять не нужно. Просто запоминаем ее наличие.
|
/// Если это уже внешняя таблица, ничего заполять не нужно. Просто запоминаем ее наличие.
|
||||||
if (external_tables.end() != external_tables.find(table->name))
|
if (external_tables.end() != external_tables.find(table->name))
|
||||||
@ -449,7 +450,7 @@ NamesAndTypesList::iterator ExpressionAnalyzer::findColumn(const String & name,
|
|||||||
/// Например, при ignore_levels=1 ast не может быть занесен в словарь, но его дети могут.
|
/// Например, при ignore_levels=1 ast не может быть занесен в словарь, но его дети могут.
|
||||||
void ExpressionAnalyzer::addASTAliases(ASTPtr & ast, int ignore_levels)
|
void ExpressionAnalyzer::addASTAliases(ASTPtr & ast, int ignore_levels)
|
||||||
{
|
{
|
||||||
ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(&*ast);
|
ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(ast.get());
|
||||||
|
|
||||||
/// Обход снизу-вверх. Не опускаемся в подзапросы.
|
/// Обход снизу-вверх. Не опускаемся в подзапросы.
|
||||||
for (auto & child : ast->children)
|
for (auto & child : ast->children)
|
||||||
@ -461,7 +462,7 @@ void ExpressionAnalyzer::addASTAliases(ASTPtr & ast, int ignore_levels)
|
|||||||
if (select && child == select->array_join_expression_list)
|
if (select && child == select->array_join_expression_list)
|
||||||
new_ignore_levels = 2;
|
new_ignore_levels = 2;
|
||||||
|
|
||||||
if (!typeid_cast<ASTSelectQuery *>(&*child))
|
if (!typeid_cast<ASTSelectQuery *>(child.get()))
|
||||||
addASTAliases(child, new_ignore_levels);
|
addASTAliases(child, new_ignore_levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,9 +482,9 @@ void ExpressionAnalyzer::addASTAliases(ASTPtr & ast, int ignore_levels)
|
|||||||
|
|
||||||
StoragePtr ExpressionAnalyzer::getTable()
|
StoragePtr ExpressionAnalyzer::getTable()
|
||||||
{
|
{
|
||||||
if (const ASTSelectQuery * select = typeid_cast<const ASTSelectQuery *>(&*ast))
|
if (const ASTSelectQuery * select = typeid_cast<const ASTSelectQuery *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (select->table && !typeid_cast<const ASTSelectQuery *>(&*select->table) && !typeid_cast<const ASTFunction *>(&*select->table))
|
if (select->table && !typeid_cast<const ASTSelectQuery *>(select->table.get()) && !typeid_cast<const ASTFunction *>(select->table.get()))
|
||||||
{
|
{
|
||||||
String database = select->database
|
String database = select->database
|
||||||
? typeid_cast<const ASTIdentifier &>(*select->database).name
|
? typeid_cast<const ASTIdentifier &>(*select->database).name
|
||||||
@ -527,7 +528,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
|
|
||||||
ASTFunction * func_node = typeid_cast<ASTFunction *>(&*ast);
|
ASTFunction * func_node = typeid_cast<ASTFunction *>(ast.get());
|
||||||
if (func_node)
|
if (func_node)
|
||||||
{
|
{
|
||||||
/** Нет ли в таблице столбца, название которого полностью совпадает с записью функции?
|
/** Нет ли в таблице столбца, название которого полностью совпадает с записью функции?
|
||||||
@ -545,7 +546,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
|
|
||||||
/// Может быть указано IN t, где t - таблица, что равносильно IN (SELECT * FROM t).
|
/// Может быть указано IN t, где t - таблица, что равносильно IN (SELECT * FROM t).
|
||||||
if (functionIsInOrGlobalInOperator(func_node->name))
|
if (functionIsInOrGlobalInOperator(func_node->name))
|
||||||
if (ASTIdentifier * right = typeid_cast<ASTIdentifier *>(&*func_node->arguments->children.at(1)))
|
if (ASTIdentifier * right = typeid_cast<ASTIdentifier *>(func_node->arguments->children.at(1).get()))
|
||||||
right->kind = ASTIdentifier::Table;
|
right->kind = ASTIdentifier::Table;
|
||||||
|
|
||||||
/// А ещё, в качестве исключения, будем понимать count(*) как count(), а не count(список всех столбцов).
|
/// А ещё, в качестве исключения, будем понимать count(*) как count(), а не count(список всех столбцов).
|
||||||
@ -555,7 +556,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
func_node->arguments->children.clear();
|
func_node->arguments->children.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
else if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (node->kind == ASTIdentifier::Column)
|
if (node->kind == ASTIdentifier::Column)
|
||||||
{
|
{
|
||||||
@ -581,13 +582,13 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ASTExpressionList * node = typeid_cast<ASTExpressionList *>(&*ast))
|
else if (ASTExpressionList * node = typeid_cast<ASTExpressionList *>(ast.get()))
|
||||||
{
|
{
|
||||||
/// Заменим * на список столбцов.
|
/// Заменим * на список столбцов.
|
||||||
ASTs & asts = node->children;
|
ASTs & asts = node->children;
|
||||||
for (int i = static_cast<int>(asts.size()) - 1; i >= 0; --i)
|
for (int i = static_cast<int>(asts.size()) - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
if (ASTAsterisk * asterisk = typeid_cast<ASTAsterisk *>(&*asts[i]))
|
if (ASTAsterisk * asterisk = typeid_cast<ASTAsterisk *>(asts[i].get()))
|
||||||
{
|
{
|
||||||
ASTs all_columns;
|
ASTs all_columns;
|
||||||
for (const auto & column_name_type : columns)
|
for (const auto & column_name_type : columns)
|
||||||
@ -598,10 +599,10 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ASTJoin * node = typeid_cast<ASTJoin *>(&*ast))
|
else if (ASTJoin * node = typeid_cast<ASTJoin *>(ast.get()))
|
||||||
{
|
{
|
||||||
/// может быть указано JOIN t, где t - таблица, что равносильно JOIN (SELECT * FROM t).
|
/// может быть указано JOIN t, где t - таблица, что равносильно JOIN (SELECT * FROM t).
|
||||||
if (ASTIdentifier * right = typeid_cast<ASTIdentifier *>(&*node->table))
|
if (ASTIdentifier * right = typeid_cast<ASTIdentifier *>(node->table.get()))
|
||||||
right->kind = ASTIdentifier::Table;
|
right->kind = ASTIdentifier::Table;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +627,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
{
|
{
|
||||||
auto & child = func_node->arguments->children[i];
|
auto & child = func_node->arguments->children[i];
|
||||||
|
|
||||||
if (typeid_cast<ASTSelectQuery *>(&*child))
|
if (typeid_cast<const ASTSelectQuery *>(child.get()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
normalizeTreeImpl(child, finished_asts, current_asts, current_alias);
|
normalizeTreeImpl(child, finished_asts, current_asts, current_alias);
|
||||||
@ -636,7 +637,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
{
|
{
|
||||||
for (auto & child : ast->children)
|
for (auto & child : ast->children)
|
||||||
{
|
{
|
||||||
if (typeid_cast<ASTSelectQuery *>(&*child))
|
if (typeid_cast<const ASTSelectQuery *>(child.get()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
normalizeTreeImpl(child, finished_asts, current_asts, current_alias);
|
normalizeTreeImpl(child, finished_asts, current_asts, current_alias);
|
||||||
@ -644,7 +645,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Если секция WHERE или HAVING состоит из одного алиаса, ссылку нужно заменить не только в children, но и в where_expression и having_expression.
|
/// Если секция WHERE или HAVING состоит из одного алиаса, ссылку нужно заменить не только в children, но и в where_expression и having_expression.
|
||||||
if (ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(&*ast))
|
if (ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (select->prewhere_expression)
|
if (select->prewhere_expression)
|
||||||
normalizeTreeImpl(select->prewhere_expression, finished_asts, current_asts, current_alias);
|
normalizeTreeImpl(select->prewhere_expression, finished_asts, current_asts, current_alias);
|
||||||
@ -656,7 +657,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
|
|
||||||
/// Действия, выполняемые снизу вверх.
|
/// Действия, выполняемые снизу вверх.
|
||||||
|
|
||||||
if (ASTFunction * node = typeid_cast<ASTFunction *>(&*ast))
|
if (ASTFunction * node = typeid_cast<ASTFunction *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (node->kind == ASTFunction::TABLE_FUNCTION)
|
if (node->kind == ASTFunction::TABLE_FUNCTION)
|
||||||
{
|
{
|
||||||
@ -995,7 +996,7 @@ void ExpressionAnalyzer::makeSetsForIndexImpl(ASTPtr & node, const Block & sampl
|
|||||||
IAST & args = *func->arguments;
|
IAST & args = *func->arguments;
|
||||||
ASTPtr & arg = args.children.at(1);
|
ASTPtr & arg = args.children.at(1);
|
||||||
|
|
||||||
if (!typeid_cast<ASTSet *>(&*arg) && !typeid_cast<ASTSubquery *>(&*arg) && !typeid_cast<ASTIdentifier *>(&*arg))
|
if (!typeid_cast<ASTSet *>(arg.get()) && !typeid_cast<ASTSubquery *>(arg.get()) && !typeid_cast<ASTIdentifier *>(arg.get()))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -1016,8 +1017,8 @@ static SharedPtr<InterpreterSelectQuery> interpretSubquery(
|
|||||||
ASTPtr & subquery_or_table_name, const Context & context, size_t subquery_depth, const Names & required_columns)
|
ASTPtr & subquery_or_table_name, const Context & context, size_t subquery_depth, const Names & required_columns)
|
||||||
{
|
{
|
||||||
/// Подзапрос или имя таблицы. Имя таблицы аналогично подзапросу SELECT * FROM t.
|
/// Подзапрос или имя таблицы. Имя таблицы аналогично подзапросу SELECT * FROM t.
|
||||||
const ASTSubquery * subquery = typeid_cast<const ASTSubquery *>(&*subquery_or_table_name);
|
const ASTSubquery * subquery = typeid_cast<const ASTSubquery *>(subquery_or_table_name.get());
|
||||||
const ASTIdentifier * table = typeid_cast<const ASTIdentifier *>(&*subquery_or_table_name);
|
const ASTIdentifier * table = typeid_cast<const ASTIdentifier *>(subquery_or_table_name.get());
|
||||||
|
|
||||||
if (!subquery && !table)
|
if (!subquery && !table)
|
||||||
throw Exception("IN/JOIN supports only SELECT subqueries.", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("IN/JOIN supports only SELECT subqueries.", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -1119,12 +1120,12 @@ void ExpressionAnalyzer::makeSet(ASTFunction * node, const Block & sample_block)
|
|||||||
ASTPtr & arg = args.children.at(1);
|
ASTPtr & arg = args.children.at(1);
|
||||||
|
|
||||||
/// Уже преобразовали.
|
/// Уже преобразовали.
|
||||||
if (typeid_cast<ASTSet *>(&*arg))
|
if (typeid_cast<ASTSet *>(arg.get()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/// Если подзапрос или имя таблицы для SELECT.
|
/// Если подзапрос или имя таблицы для SELECT.
|
||||||
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(&*arg);
|
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(arg.get());
|
||||||
if (typeid_cast<ASTSubquery *>(&*arg) || identifier)
|
if (typeid_cast<ASTSubquery *>(arg.get()) || identifier)
|
||||||
{
|
{
|
||||||
/// Получаем поток блоков для подзапроса. Создаём Set и кладём на место подзапроса.
|
/// Получаем поток блоков для подзапроса. Создаём Set и кладём на место подзапроса.
|
||||||
String set_id = arg->getColumnName();
|
String set_id = arg->getColumnName();
|
||||||
@ -1225,7 +1226,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
|
|||||||
DataTypes set_element_types;
|
DataTypes set_element_types;
|
||||||
ASTPtr & left_arg = args.children.at(0);
|
ASTPtr & left_arg = args.children.at(0);
|
||||||
|
|
||||||
ASTFunction * left_arg_tuple = typeid_cast<ASTFunction *>(&*left_arg);
|
ASTFunction * left_arg_tuple = typeid_cast<ASTFunction *>(left_arg.get());
|
||||||
|
|
||||||
if (left_arg_tuple && left_arg_tuple->name == "tuple")
|
if (left_arg_tuple && left_arg_tuple->name == "tuple")
|
||||||
{
|
{
|
||||||
@ -1243,7 +1244,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataTypePtr left_type = sample_block.getByName(left_arg->getColumnName()).type;
|
DataTypePtr left_type = sample_block.getByName(left_arg->getColumnName()).type;
|
||||||
if (DataTypeArray * array_type = typeid_cast<DataTypeArray *>(&*left_type))
|
if (DataTypeArray * array_type = typeid_cast<DataTypeArray *>(left_type.get()))
|
||||||
set_element_types.push_back(array_type->getNestedType());
|
set_element_types.push_back(array_type->getNestedType());
|
||||||
else
|
else
|
||||||
set_element_types.push_back(left_type);
|
set_element_types.push_back(left_type);
|
||||||
@ -1253,7 +1254,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
|
|||||||
bool single_value = false;
|
bool single_value = false;
|
||||||
ASTPtr elements_ast = arg;
|
ASTPtr elements_ast = arg;
|
||||||
|
|
||||||
if (ASTFunction * set_func = typeid_cast<ASTFunction *>(&*arg))
|
if (ASTFunction * set_func = typeid_cast<ASTFunction *>(arg.get()))
|
||||||
{
|
{
|
||||||
if (set_func->name == "tuple")
|
if (set_func->name == "tuple")
|
||||||
{
|
{
|
||||||
@ -1265,7 +1266,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/// Отличм случай (x, y) in ((1, 2), (3, 4)) от случая (x, y) in (1, 2).
|
/// Отличм случай (x, y) in ((1, 2), (3, 4)) от случая (x, y) in (1, 2).
|
||||||
ASTFunction * any_element = typeid_cast<ASTFunction *>(&*set_func->arguments->children.at(0));
|
ASTFunction * any_element = typeid_cast<ASTFunction *>(set_func->arguments->children.at(0).get());
|
||||||
if (set_element_types.size() >= 2 && (!any_element || any_element->name != "tuple"))
|
if (set_element_types.size() >= 2 && (!any_element || any_element->name != "tuple"))
|
||||||
single_value = true;
|
single_value = true;
|
||||||
else
|
else
|
||||||
@ -1282,7 +1283,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
|
|||||||
single_value = true;
|
single_value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (typeid_cast<ASTLiteral *>(&*arg))
|
else if (typeid_cast<ASTLiteral *>(arg.get()))
|
||||||
{
|
{
|
||||||
single_value = true;
|
single_value = true;
|
||||||
}
|
}
|
||||||
@ -1436,7 +1437,7 @@ void ExpressionAnalyzer::getArrayJoinedColumns()
|
|||||||
const String nested_table_name = ast->getColumnName();
|
const String nested_table_name = ast->getColumnName();
|
||||||
const String nested_table_alias = ast->getAliasOrColumnName();
|
const String nested_table_alias = ast->getAliasOrColumnName();
|
||||||
|
|
||||||
if (nested_table_alias == nested_table_name && !typeid_cast<const ASTIdentifier *>(&*ast))
|
if (nested_table_alias == nested_table_name && !typeid_cast<const ASTIdentifier *>(ast.get()))
|
||||||
throw Exception("No alias for non-trivial value in ARRAY JOIN: " + nested_table_name, ErrorCodes::ALIAS_REQUIRED);
|
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))
|
if (array_join_alias_to_name.count(nested_table_alias) || aliases.count(nested_table_alias))
|
||||||
@ -1466,7 +1467,7 @@ void ExpressionAnalyzer::getArrayJoinedColumns()
|
|||||||
String result_name = expr->getAliasOrColumnName();
|
String result_name = expr->getAliasOrColumnName();
|
||||||
|
|
||||||
/// Это массив.
|
/// Это массив.
|
||||||
if (!typeid_cast<ASTIdentifier *>(&*expr) || findColumn(source_name, columns) != columns.end())
|
if (!typeid_cast<ASTIdentifier *>(expr.get()) || findColumn(source_name, columns) != columns.end())
|
||||||
{
|
{
|
||||||
array_join_result_to_source[result_name] = source_name;
|
array_join_result_to_source[result_name] = source_name;
|
||||||
}
|
}
|
||||||
@ -1495,7 +1496,7 @@ void ExpressionAnalyzer::getArrayJoinedColumns()
|
|||||||
/// Заполняет array_join_result_to_source: по каким столбцам-массивам размножить, и как их после этого назвать.
|
/// Заполняет array_join_result_to_source: по каким столбцам-массивам размножить, и как их после этого назвать.
|
||||||
void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast)
|
void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast)
|
||||||
{
|
{
|
||||||
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (node->kind == ASTIdentifier::Column)
|
if (node->kind == ASTIdentifier::Column)
|
||||||
{
|
{
|
||||||
@ -1528,7 +1529,7 @@ void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (auto & child : ast->children)
|
for (auto & child : ast->children)
|
||||||
if (!typeid_cast<const ASTSelectQuery *>(&*child))
|
if (!typeid_cast<const ASTSelectQuery *>(child.get()))
|
||||||
getArrayJoinedColumnsImpl(child);
|
getArrayJoinedColumnsImpl(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1537,11 +1538,11 @@ void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast)
|
|||||||
void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack)
|
void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack)
|
||||||
{
|
{
|
||||||
/// Если результат вычисления уже есть в блоке.
|
/// Если результат вычисления уже есть в блоке.
|
||||||
if ((typeid_cast<ASTFunction *>(&*ast) || typeid_cast<ASTLiteral *>(&*ast))
|
if ((typeid_cast<ASTFunction *>(ast.get()) || typeid_cast<ASTLiteral *>(ast.get()))
|
||||||
&& actions_stack.getSampleBlock().has(ast->getColumnName()))
|
&& actions_stack.getSampleBlock().has(ast->getColumnName()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(ast.get()))
|
||||||
{
|
{
|
||||||
std::string name = node->getColumnName();
|
std::string name = node->getColumnName();
|
||||||
if (!only_consts && !actions_stack.getSampleBlock().has(name))
|
if (!only_consts && !actions_stack.getSampleBlock().has(name))
|
||||||
@ -1559,10 +1560,10 @@ void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool onl
|
|||||||
ErrorCodes::NOT_AN_AGGREGATE);
|
ErrorCodes::NOT_AN_AGGREGATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ASTFunction * node = typeid_cast<ASTFunction *>(&*ast))
|
else if (ASTFunction * node = typeid_cast<ASTFunction *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (node->kind == ASTFunction::LAMBDA_EXPRESSION)
|
if (node->kind == ASTFunction::LAMBDA_EXPRESSION)
|
||||||
throw Exception("Unexpected expression", ErrorCodes::UNEXPECTED_EXPRESSION);
|
throw Exception("Unexpected lambda expression", ErrorCodes::UNEXPECTED_EXPRESSION);
|
||||||
|
|
||||||
/// Функция arrayJoin.
|
/// Функция arrayJoin.
|
||||||
if (node->kind == ASTFunction::ARRAY_JOIN)
|
if (node->kind == ASTFunction::ARRAY_JOIN)
|
||||||
@ -1623,15 +1624,15 @@ void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool onl
|
|||||||
|
|
||||||
for (auto & child : node->arguments->children)
|
for (auto & child : node->arguments->children)
|
||||||
{
|
{
|
||||||
ASTFunction * lambda = typeid_cast<ASTFunction *>(&*child);
|
ASTFunction * lambda = typeid_cast<ASTFunction *>(child.get());
|
||||||
ASTSet * set = typeid_cast<ASTSet *>(&*child);
|
ASTSet * set = typeid_cast<ASTSet *>(child.get());
|
||||||
if (lambda && lambda->name == "lambda")
|
if (lambda && lambda->name == "lambda")
|
||||||
{
|
{
|
||||||
/// Если аргумент - лямбда-выражение, только запомним его примерный тип.
|
/// Если аргумент - лямбда-выражение, только запомним его примерный тип.
|
||||||
if (lambda->arguments->children.size() != 2)
|
if (lambda->arguments->children.size() != 2)
|
||||||
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||||
|
|
||||||
ASTFunction * lambda_args_tuple = typeid_cast<ASTFunction *>(&*lambda->arguments->children.at(0));
|
ASTFunction * lambda_args_tuple = typeid_cast<ASTFunction *>(lambda->arguments->children.at(0).get());
|
||||||
|
|
||||||
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
||||||
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
||||||
@ -1701,17 +1702,17 @@ void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool onl
|
|||||||
{
|
{
|
||||||
ASTPtr child = node->arguments->children[i];
|
ASTPtr child = node->arguments->children[i];
|
||||||
|
|
||||||
ASTFunction * lambda = typeid_cast<ASTFunction *>(&*child);
|
ASTFunction * lambda = typeid_cast<ASTFunction *>(child.get());
|
||||||
if (lambda && lambda->name == "lambda")
|
if (lambda && lambda->name == "lambda")
|
||||||
{
|
{
|
||||||
DataTypeExpression * lambda_type = typeid_cast<DataTypeExpression *>(&*argument_types[i]);
|
DataTypeExpression * lambda_type = typeid_cast<DataTypeExpression *>(argument_types[i].get());
|
||||||
ASTFunction * lambda_args_tuple = typeid_cast<ASTFunction *>(&*lambda->arguments->children.at(0));
|
ASTFunction * lambda_args_tuple = typeid_cast<ASTFunction *>(lambda->arguments->children.at(0).get());
|
||||||
ASTs lambda_arg_asts = lambda_args_tuple->arguments->children;
|
ASTs lambda_arg_asts = lambda_args_tuple->arguments->children;
|
||||||
NamesAndTypesList lambda_arguments;
|
NamesAndTypesList lambda_arguments;
|
||||||
|
|
||||||
for (size_t j = 0; j < lambda_arg_asts.size(); ++j)
|
for (size_t j = 0; j < lambda_arg_asts.size(); ++j)
|
||||||
{
|
{
|
||||||
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(&*lambda_arg_asts[j]);
|
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(lambda_arg_asts[j].get());
|
||||||
if (!identifier)
|
if (!identifier)
|
||||||
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
||||||
|
|
||||||
@ -1764,7 +1765,7 @@ void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool onl
|
|||||||
additional_requirements);
|
additional_requirements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ASTLiteral * node = typeid_cast<ASTLiteral *>(&*ast))
|
else if (ASTLiteral * node = typeid_cast<ASTLiteral *>(ast.get()))
|
||||||
{
|
{
|
||||||
DataTypePtr type = apply_visitor(FieldToDataType(), node->value);
|
DataTypePtr type = apply_visitor(FieldToDataType(), node->value);
|
||||||
|
|
||||||
@ -1783,9 +1784,23 @@ void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool onl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExpressionAnalyzer::getAggregates(ASTPtr ast, ExpressionActionsPtr & actions)
|
void ExpressionAnalyzer::getAggregates(const ASTPtr & ast, ExpressionActionsPtr & actions)
|
||||||
{
|
{
|
||||||
ASTFunction * node = typeid_cast<ASTFunction *>(&*ast);
|
/// Внутри WHERE и PREWHERE не может быть агрегатных функций.
|
||||||
|
if (select_query && (ast.get() == select_query->where_expression.get() || ast.get() == select_query->prewhere_expression.get()))
|
||||||
|
{
|
||||||
|
assertNoAggregates(ast, "in WHERE or PREWHERE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Если мы анализируем не запрос SELECT, а отдельное выражение, то в нём не может быть агрегатных функций.
|
||||||
|
if (!select_query)
|
||||||
|
{
|
||||||
|
assertNoAggregates(ast, "in wrong place");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ASTFunction * node = typeid_cast<const ASTFunction *>(ast.get());
|
||||||
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
||||||
{
|
{
|
||||||
has_aggregation = true;
|
has_aggregation = true;
|
||||||
@ -1797,12 +1812,15 @@ void ExpressionAnalyzer::getAggregates(ASTPtr ast, ExpressionActionsPtr & action
|
|||||||
if (aggregate_descriptions[i].column_name == aggregate.column_name)
|
if (aggregate_descriptions[i].column_name == aggregate.column_name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASTs & arguments = node->arguments->children;
|
const ASTs & arguments = node->arguments->children;
|
||||||
aggregate.argument_names.resize(arguments.size());
|
aggregate.argument_names.resize(arguments.size());
|
||||||
DataTypes types(arguments.size());
|
DataTypes types(arguments.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < arguments.size(); ++i)
|
for (size_t i = 0; i < arguments.size(); ++i)
|
||||||
{
|
{
|
||||||
|
/// Внутри агрегатных функций не может быть других агрегатных функций.
|
||||||
|
assertNoAggregates(arguments[i], "inside another aggregate function");
|
||||||
|
|
||||||
getRootActions(arguments[i], true, false, actions);
|
getRootActions(arguments[i], true, false, actions);
|
||||||
const std::string & name = arguments[i]->getColumnName();
|
const std::string & name = arguments[i]->getColumnName();
|
||||||
types[i] = actions->getSampleBlock().getByName(name).type;
|
types[i] = actions->getSampleBlock().getByName(name).type;
|
||||||
@ -1813,14 +1831,15 @@ void ExpressionAnalyzer::getAggregates(ASTPtr ast, ExpressionActionsPtr & action
|
|||||||
|
|
||||||
if (node->parameters)
|
if (node->parameters)
|
||||||
{
|
{
|
||||||
ASTs & parameters = typeid_cast<ASTExpressionList &>(*node->parameters).children;
|
const ASTs & parameters = typeid_cast<const ASTExpressionList &>(*node->parameters).children;
|
||||||
Array params_row(parameters.size());
|
Array params_row(parameters.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < parameters.size(); ++i)
|
for (size_t i = 0; i < parameters.size(); ++i)
|
||||||
{
|
{
|
||||||
ASTLiteral * lit = typeid_cast<ASTLiteral *>(&*parameters[i]);
|
const ASTLiteral * lit = typeid_cast<const ASTLiteral *>(parameters[i].get());
|
||||||
if (!lit)
|
if (!lit)
|
||||||
throw Exception("Parameters to aggregate functions must be literals", ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS);
|
throw Exception("Parameters to aggregate functions must be literals",
|
||||||
|
ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS);
|
||||||
|
|
||||||
params_row[i] = lit->value;
|
params_row[i] = lit->value;
|
||||||
}
|
}
|
||||||
@ -1835,15 +1854,27 @@ void ExpressionAnalyzer::getAggregates(ASTPtr ast, ExpressionActionsPtr & action
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ast->children.size(); ++i)
|
for (const auto & child : ast->children)
|
||||||
{
|
if (!typeid_cast<const ASTSubquery *>(child.get()) && !typeid_cast<const ASTSelectQuery *>(child.get()))
|
||||||
ASTPtr child = ast->children[i];
|
|
||||||
if (!typeid_cast<ASTSubquery *>(&*child) && !typeid_cast<ASTSelectQuery *>(&*child))
|
|
||||||
getAggregates(child, actions);
|
getAggregates(child, actions);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExpressionAnalyzer::assertNoAggregates(const ASTPtr & ast, const char * description)
|
||||||
|
{
|
||||||
|
const ASTFunction * node = typeid_cast<const ASTFunction *>(ast.get());
|
||||||
|
|
||||||
|
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
||||||
|
throw Exception("Aggregate function " + node->getColumnName()
|
||||||
|
+ " is found " + String(description) + " in query", ErrorCodes::ILLEGAL_AGGREGATION);
|
||||||
|
|
||||||
|
for (const auto & child : ast->children)
|
||||||
|
if (!typeid_cast<const ASTSubquery *>(child.get()) && !typeid_cast<const ASTSelectQuery *>(child.get()))
|
||||||
|
assertNoAggregates(child, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExpressionAnalyzer::assertSelect() const
|
void ExpressionAnalyzer::assertSelect() const
|
||||||
{
|
{
|
||||||
if (!select_query)
|
if (!select_query)
|
||||||
@ -1930,7 +1961,7 @@ bool ExpressionAnalyzer::appendJoin(ExpressionActionsChain & chain, bool only_ty
|
|||||||
|
|
||||||
/// Особый случай - если справа JOIN указано имя таблицы, при чём, таблица имеет тип Join (заранее подготовленное отображение).
|
/// Особый случай - если справа JOIN указано имя таблицы, при чём, таблица имеет тип Join (заранее подготовленное отображение).
|
||||||
/// TODO В этом синтаксисе не поддерживается указание имени БД.
|
/// TODO В этом синтаксисе не поддерживается указание имени БД.
|
||||||
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(&*ast_join.table);
|
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(ast_join.table.get());
|
||||||
if (identifier)
|
if (identifier)
|
||||||
{
|
{
|
||||||
StoragePtr table = context.tryGetTable("", identifier->name);
|
StoragePtr table = context.tryGetTable("", identifier->name);
|
||||||
@ -2087,7 +2118,7 @@ bool ExpressionAnalyzer::appendOrderBy(ExpressionActionsChain & chain, bool only
|
|||||||
ASTs asts = select_query->order_expression_list->children;
|
ASTs asts = select_query->order_expression_list->children;
|
||||||
for (size_t i = 0; i < asts.size(); ++i)
|
for (size_t i = 0; i < asts.size(); ++i)
|
||||||
{
|
{
|
||||||
ASTOrderByElement * ast = typeid_cast<ASTOrderByElement *>(&*asts[i]);
|
ASTOrderByElement * ast = typeid_cast<ASTOrderByElement *>(asts[i].get());
|
||||||
if (!ast || ast->children.size() != 1)
|
if (!ast || ast->children.size() != 1)
|
||||||
throw Exception("Bad order expression AST", ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
throw Exception("Bad order expression AST", ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
||||||
ASTPtr order_expression = ast->children.at(0);
|
ASTPtr order_expression = ast->children.at(0);
|
||||||
@ -2138,7 +2169,7 @@ Block ExpressionAnalyzer::getSelectSampleBlock()
|
|||||||
|
|
||||||
void ExpressionAnalyzer::getActionsBeforeAggregation(ASTPtr ast, ExpressionActionsPtr & actions, bool no_subqueries)
|
void ExpressionAnalyzer::getActionsBeforeAggregation(ASTPtr ast, ExpressionActionsPtr & actions, bool no_subqueries)
|
||||||
{
|
{
|
||||||
ASTFunction * node = typeid_cast<ASTFunction *>(&*ast);
|
ASTFunction * node = typeid_cast<ASTFunction *>(ast.get());
|
||||||
|
|
||||||
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
||||||
for (auto & argument : node->arguments->children)
|
for (auto & argument : node->arguments->children)
|
||||||
@ -2157,7 +2188,7 @@ ExpressionActionsPtr ExpressionAnalyzer::getActions(bool project_result)
|
|||||||
|
|
||||||
ASTs asts;
|
ASTs asts;
|
||||||
|
|
||||||
if (auto node = typeid_cast<const ASTExpressionList *>(&*ast))
|
if (auto node = typeid_cast<const ASTExpressionList *>(ast.get()))
|
||||||
asts = node->children;
|
asts = node->children;
|
||||||
else
|
else
|
||||||
asts = ASTs(1, ast);
|
asts = ASTs(1, ast);
|
||||||
@ -2226,7 +2257,7 @@ void ExpressionAnalyzer::collectUsedColumns()
|
|||||||
{
|
{
|
||||||
/// Игнорируем идентификаторы верхнего уровня из секции ARRAY JOIN.
|
/// Игнорируем идентификаторы верхнего уровня из секции ARRAY JOIN.
|
||||||
/// Их потом добавим отдельно.
|
/// Их потом добавим отдельно.
|
||||||
if (typeid_cast<ASTIdentifier *>(&*expressions[i]))
|
if (typeid_cast<ASTIdentifier *>(expressions[i].get()))
|
||||||
{
|
{
|
||||||
ignored.insert(expressions[i]->getColumnName());
|
ignored.insert(expressions[i]->getColumnName());
|
||||||
}
|
}
|
||||||
@ -2389,7 +2420,7 @@ void ExpressionAnalyzer::getRequiredColumnsImpl(ASTPtr ast,
|
|||||||
* - идентификаторы, доступные из JOIN-а, кладём в required_joined_columns.
|
* - идентификаторы, доступные из JOIN-а, кладём в required_joined_columns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (node->kind == ASTIdentifier::Column
|
if (node->kind == ASTIdentifier::Column
|
||||||
&& !ignored_names.count(node->name)
|
&& !ignored_names.count(node->name)
|
||||||
@ -2404,14 +2435,14 @@ void ExpressionAnalyzer::getRequiredColumnsImpl(ASTPtr ast,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ASTFunction * node = typeid_cast<ASTFunction *>(&*ast))
|
if (ASTFunction * node = typeid_cast<ASTFunction *>(ast.get()))
|
||||||
{
|
{
|
||||||
if (node->kind == ASTFunction::LAMBDA_EXPRESSION)
|
if (node->kind == ASTFunction::LAMBDA_EXPRESSION)
|
||||||
{
|
{
|
||||||
if (node->arguments->children.size() != 2)
|
if (node->arguments->children.size() != 2)
|
||||||
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||||
|
|
||||||
ASTFunction * lambda_args_tuple = typeid_cast<ASTFunction *>(&*node->arguments->children.at(0));
|
ASTFunction * lambda_args_tuple = typeid_cast<ASTFunction *>(node->arguments->children.at(0).get());
|
||||||
|
|
||||||
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
||||||
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
||||||
@ -2420,7 +2451,7 @@ void ExpressionAnalyzer::getRequiredColumnsImpl(ASTPtr ast,
|
|||||||
Names added_ignored;
|
Names added_ignored;
|
||||||
for (auto & child : lambda_args_tuple->arguments->children)
|
for (auto & child : lambda_args_tuple->arguments->children)
|
||||||
{
|
{
|
||||||
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(&*child);
|
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(child.get());
|
||||||
if (!identifier)
|
if (!identifier)
|
||||||
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
||||||
|
|
||||||
@ -2443,7 +2474,7 @@ void ExpressionAnalyzer::getRequiredColumnsImpl(ASTPtr ast,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(&*ast);
|
ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(ast.get());
|
||||||
|
|
||||||
/// Рекурсивный обход выражения.
|
/// Рекурсивный обход выражения.
|
||||||
for (auto & child : ast->children)
|
for (auto & child : ast->children)
|
||||||
@ -2451,7 +2482,7 @@ void ExpressionAnalyzer::getRequiredColumnsImpl(ASTPtr ast,
|
|||||||
/** Не пойдем в секцию ARRAY JOIN, потому что там нужно смотреть на имена не-ARRAY-JOIN-енных столбцов.
|
/** Не пойдем в секцию ARRAY JOIN, потому что там нужно смотреть на имена не-ARRAY-JOIN-енных столбцов.
|
||||||
* Туда collectUsedColumns отправит нас отдельно.
|
* Туда collectUsedColumns отправит нас отдельно.
|
||||||
*/
|
*/
|
||||||
if (!typeid_cast<ASTSubquery *>(&*child) && !typeid_cast<ASTSelectQuery *>(&*child) &&
|
if (!typeid_cast<ASTSubquery *>(child.get()) && !typeid_cast<ASTSelectQuery *>(child.get()) &&
|
||||||
!(select && child == select->array_join_expression_list))
|
!(select && child == select->array_join_expression_list))
|
||||||
getRequiredColumnsImpl(child, required_columns, ignored_names, available_joined_columns, required_joined_columns);
|
getRequiredColumnsImpl(child, required_columns, ignored_names, available_joined_columns, required_joined_columns);
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,8 @@ BlockInputStreams MergeTreeDataSelectExecutor::read(
|
|||||||
else if (typeid_cast<const DataTypeUInt8 *>(type.get()))
|
else if (typeid_cast<const DataTypeUInt8 *>(type.get()))
|
||||||
size_of_universum = RelativeSize(std::numeric_limits<UInt8>::max()) + 1;
|
size_of_universum = RelativeSize(std::numeric_limits<UInt8>::max()) + 1;
|
||||||
else
|
else
|
||||||
throw Exception("Invalid sampling column type in storage parameters: " + type->getName() + ". Must be unsigned integer type.", ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
|
throw Exception("Invalid sampling column type in storage parameters: " + type->getName() + ". Must be unsigned integer type.",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
|
||||||
|
|
||||||
if (settings.parallel_replicas_count > 1)
|
if (settings.parallel_replicas_count > 1)
|
||||||
{
|
{
|
||||||
@ -578,10 +579,11 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongThreads(
|
|||||||
prewhere_column, settings, virt_columns
|
prewhere_column, settings, virt_columns
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
{
|
||||||
/// Выставим приблизительное количество строк только для первого источника
|
/// Выставим приблизительное количество строк только для первого источника
|
||||||
static_cast<IProfilingBlockInputStream &>(*res.front()).setTotalRowsApprox(total_rows);
|
static_cast<IProfilingBlockInputStream &>(*res.front()).setTotalRowsApprox(total_rows);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sum_marks > 0)
|
else if (sum_marks > 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user