mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 09:32:01 +00:00
dbms: better [#METR-11370].
This commit is contained in:
parent
2fa4a2cf60
commit
8a7a4b11f0
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <DB/Parsers/IAST.h>
|
#include <DB/Parsers/ASTWithAlias.h>
|
||||||
#include <DB/Functions/IFunction.h>
|
#include <DB/Functions/IFunction.h>
|
||||||
#include <DB/AggregateFunctions/IAggregateFunction.h>
|
#include <DB/AggregateFunctions/IAggregateFunction.h>
|
||||||
#include <DB/IO/WriteBufferFromString.h>
|
#include <DB/IO/WriteBufferFromString.h>
|
||||||
@ -11,7 +11,7 @@ namespace DB
|
|||||||
|
|
||||||
/** Применение функции или оператора
|
/** Применение функции или оператора
|
||||||
*/
|
*/
|
||||||
class ASTFunction : public IAST
|
class ASTFunction : public ASTWithAlias
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum FunctionKind
|
enum FunctionKind
|
||||||
@ -23,20 +23,18 @@ public:
|
|||||||
LAMBDA_EXPRESSION,
|
LAMBDA_EXPRESSION,
|
||||||
ARRAY_JOIN,
|
ARRAY_JOIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// имя функции
|
/// имя функции
|
||||||
String name;
|
String name;
|
||||||
/// аргументы
|
/// аргументы
|
||||||
ASTPtr arguments;
|
ASTPtr arguments;
|
||||||
/// параметры - для параметрических агрегатных функций. Пример: quantile(0.9)(x) - то, что в первых скобках - параметры.
|
/// параметры - для параметрических агрегатных функций. Пример: quantile(0.9)(x) - то, что в первых скобках - параметры.
|
||||||
ASTPtr parameters;
|
ASTPtr parameters;
|
||||||
/// алиас, если есть
|
|
||||||
String alias;
|
|
||||||
|
|
||||||
FunctionKind kind;
|
FunctionKind kind;
|
||||||
|
|
||||||
ASTFunction() : kind(UNKNOWN) {}
|
ASTFunction() : kind(UNKNOWN) {}
|
||||||
ASTFunction(StringRange range_) : IAST(range_), kind(UNKNOWN) {}
|
ASTFunction(StringRange range_) : ASTWithAlias(range_), kind(UNKNOWN) {}
|
||||||
|
|
||||||
String getColumnName() const
|
String getColumnName() const
|
||||||
{
|
{
|
||||||
@ -68,8 +66,6 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getAlias() const { return alias.empty() ? getColumnName() : alias; }
|
|
||||||
|
|
||||||
/** Получить текст, который идентифицирует этот элемент. */
|
/** Получить текст, который идентифицирует этот элемент. */
|
||||||
String getID() const { return "Function_" + name; }
|
String getID() const { return "Function_" + name; }
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <DB/DataTypes/IDataType.h>
|
#include <DB/DataTypes/IDataType.h>
|
||||||
#include <DB/Parsers/IAST.h>
|
#include <DB/Parsers/ASTWithAlias.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
@ -9,7 +9,7 @@ namespace DB
|
|||||||
|
|
||||||
/** Идентификатор (столбца или алиас, или именованый элемент кортежа)
|
/** Идентификатор (столбца или алиас, или именованый элемент кортежа)
|
||||||
*/
|
*/
|
||||||
class ASTIdentifier : public IAST
|
class ASTIdentifier : public ASTWithAlias
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Kind
|
enum Kind
|
||||||
@ -19,22 +19,18 @@ public:
|
|||||||
Table,
|
Table,
|
||||||
Format,
|
Format,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// имя
|
/// имя
|
||||||
String name;
|
String name;
|
||||||
/// алиас, если есть
|
|
||||||
String alias;
|
|
||||||
|
|
||||||
/// чего идентифицирует этот идентификатор
|
/// чего идентифицирует этот идентификатор
|
||||||
Kind kind;
|
Kind kind;
|
||||||
|
|
||||||
ASTIdentifier() {}
|
ASTIdentifier() {}
|
||||||
ASTIdentifier(StringRange range_, const String & name_, Kind kind_ = Column) : IAST(range_), name(name_), kind(kind_) {}
|
ASTIdentifier(StringRange range_, const String & name_, Kind kind_ = Column) : ASTWithAlias(range_), name(name_), kind(kind_) {}
|
||||||
|
|
||||||
String getColumnName() const { return name; }
|
String getColumnName() const { return name; }
|
||||||
|
|
||||||
String getAlias() const { return alias.empty() ? getColumnName() : alias; }
|
|
||||||
|
|
||||||
/** Получить текст, который идентифицирует этот элемент. */
|
/** Получить текст, который идентифицирует этот элемент. */
|
||||||
String getID() const { return "Identifier_" + name; }
|
String getID() const { return "Identifier_" + name; }
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <DB/Core/Field.h>
|
#include <DB/Core/Field.h>
|
||||||
#include <DB/DataTypes/IDataType.h>
|
#include <DB/DataTypes/IDataType.h>
|
||||||
#include <DB/Parsers/IAST.h>
|
#include <DB/Parsers/ASTWithAlias.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
@ -10,22 +10,18 @@ namespace DB
|
|||||||
|
|
||||||
/** Литерал (атомарный) - число, строка, NULL
|
/** Литерал (атомарный) - число, строка, NULL
|
||||||
*/
|
*/
|
||||||
class ASTLiteral : public IAST
|
class ASTLiteral : public ASTWithAlias
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Field value;
|
Field value;
|
||||||
/// тип
|
/// тип
|
||||||
DataTypePtr type;
|
DataTypePtr type;
|
||||||
/// алиас, если есть
|
|
||||||
String alias;
|
|
||||||
|
|
||||||
ASTLiteral() {}
|
ASTLiteral() {}
|
||||||
ASTLiteral(StringRange range_, const Field & value_) : IAST(range_), value(value_) {}
|
ASTLiteral(StringRange range_, const Field & value_) : ASTWithAlias(range_), value(value_) {}
|
||||||
|
|
||||||
String getColumnName() const { return apply_visitor(FieldVisitorToString(), value); }
|
String getColumnName() const { return apply_visitor(FieldVisitorToString(), value); }
|
||||||
|
|
||||||
String getAlias() const { return alias.empty() ? getColumnName() : alias; }
|
|
||||||
|
|
||||||
/** Получить текст, который идентифицирует этот элемент. */
|
/** Получить текст, который идентифицирует этот элемент. */
|
||||||
String getID() const { return "Literal_" + apply_visitor(FieldVisitorDump(), value); }
|
String getID() const { return "Literal_" + apply_visitor(FieldVisitorDump(), value); }
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ public:
|
|||||||
bool done = 0;
|
bool done = 0;
|
||||||
for (size_t j = 0; j < asts.size(); ++j)
|
for (size_t j = 0; j < asts.size(); ++j)
|
||||||
{
|
{
|
||||||
if (asts[j]->getAlias() == column_names[i])
|
if (asts[j]->getAliasOrColumnName() == column_names[i])
|
||||||
{
|
{
|
||||||
if (!unremovable_asts.count(asts[j]))
|
if (!unremovable_asts.count(asts[j]))
|
||||||
result->children.push_back(asts[j]->clone());
|
result->children.push_back(asts[j]->clone());
|
||||||
|
24
dbms/include/DB/Parsers/ASTWithAlias.h
Normal file
24
dbms/include/DB/Parsers/ASTWithAlias.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <DB/Parsers/IAST.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Базовый класс для AST, которые могут содержать алиас (идентификаторы, литералы, функции).
|
||||||
|
*/
|
||||||
|
class ASTWithAlias : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Алиас, если есть, или пустая строка.
|
||||||
|
String alias;
|
||||||
|
|
||||||
|
using IAST::IAST;
|
||||||
|
|
||||||
|
String getAliasOrColumnName() const override { return alias.empty() ? getColumnName() : alias; }
|
||||||
|
String tryGetAlias() const override { return alias; }
|
||||||
|
void setAlias(const String & to) override { alias = to; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -32,7 +32,7 @@ public:
|
|||||||
typedef std::vector<SharedPtr<IAST> > ASTs;
|
typedef std::vector<SharedPtr<IAST> > ASTs;
|
||||||
ASTs children;
|
ASTs children;
|
||||||
StringRange range;
|
StringRange range;
|
||||||
|
|
||||||
/** Строка с полным запросом.
|
/** Строка с полным запросом.
|
||||||
* Этот указатель не дает ее удалить, пока range в нее ссылается.
|
* Этот указатель не дает ее удалить, пока range в нее ссылается.
|
||||||
*/
|
*/
|
||||||
@ -45,9 +45,18 @@ public:
|
|||||||
/** Получить каноническое имя столбца, если элемент является столбцом */
|
/** Получить каноническое имя столбца, если элемент является столбцом */
|
||||||
virtual String getColumnName() const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); }
|
virtual String getColumnName() const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); }
|
||||||
|
|
||||||
/** Получить алиас, если он есть, или каноническое имя столбца; если элемент является столбцом */
|
/** Получить алиас, если он есть, или каноническое имя столбца, если его нет. */
|
||||||
virtual String getAlias() const { return getColumnName(); }
|
virtual String getAliasOrColumnName() const { return getColumnName(); }
|
||||||
|
|
||||||
|
/** Получить алиас, если он есть, или пустую строку, если его нет, или если элемент не поддерживает алиасы. */
|
||||||
|
virtual String tryGetAlias() const { return String(); }
|
||||||
|
|
||||||
|
/** Установить алиас. */
|
||||||
|
virtual void setAlias(const String & to)
|
||||||
|
{
|
||||||
|
throw Exception("Can't set alias of " + getColumnName(), ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
||||||
|
}
|
||||||
|
|
||||||
/** Получить текст, который идентифицирует этот элемент. */
|
/** Получить текст, который идентифицирует этот элемент. */
|
||||||
virtual String getID() const = 0;
|
virtual String getID() const = 0;
|
||||||
|
|
||||||
@ -55,7 +64,7 @@ public:
|
|||||||
virtual SharedPtr<IAST> clone() const = 0;
|
virtual SharedPtr<IAST> clone() const = 0;
|
||||||
|
|
||||||
/** Получить текст, который идентифицирует этот элемент и всё поддерево.
|
/** Получить текст, который идентифицирует этот элемент и всё поддерево.
|
||||||
* Обычно он содержит идентификатор элемента и getTreeID от всех детей.
|
* Обычно он содержит идентификатор элемента и getTreeID от всех детей.
|
||||||
*/
|
*/
|
||||||
String getTreeID() const
|
String getTreeID() const
|
||||||
{
|
{
|
||||||
@ -93,7 +102,7 @@ public:
|
|||||||
{
|
{
|
||||||
return checkDepthImpl(max_depth, 0);
|
return checkDepthImpl(max_depth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** То же самое для общего количества элементов дерева.
|
/** То же самое для общего количества элементов дерева.
|
||||||
*/
|
*/
|
||||||
size_t checkSize(size_t max_size) const
|
size_t checkSize(size_t max_size) const
|
||||||
@ -104,7 +113,7 @@ public:
|
|||||||
|
|
||||||
if (res > max_size)
|
if (res > max_size)
|
||||||
throw Exception("AST is too big. Maximum: " + toString(max_size), ErrorCodes::TOO_BIG_AST);
|
throw Exception("AST is too big. Maximum: " + toString(max_size), ErrorCodes::TOO_BIG_AST);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,31 +37,6 @@ namespace DB
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
static std::string * tryGetAlias(ASTPtr & ast)
|
|
||||||
{
|
|
||||||
if (ASTFunction * node = typeid_cast<ASTFunction *>(&*ast))
|
|
||||||
return &node->alias;
|
|
||||||
else if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
|
||||||
return &node->alias;
|
|
||||||
else if (ASTLiteral * node = typeid_cast<ASTLiteral *>(&*ast))
|
|
||||||
return &node->alias;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAlias(ASTPtr & ast, const std::string & alias)
|
|
||||||
{
|
|
||||||
if (ASTFunction * node = typeid_cast<ASTFunction *>(&*ast))
|
|
||||||
node->alias = alias;
|
|
||||||
else if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(&*ast))
|
|
||||||
node->alias = alias;
|
|
||||||
else if (ASTLiteral * node = typeid_cast<ASTLiteral *>(&*ast))
|
|
||||||
node->alias = alias;
|
|
||||||
else
|
|
||||||
throw Exception("Can't set alias of " + ast->getColumnName(), ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ExpressionAnalyzer::init()
|
void ExpressionAnalyzer::init()
|
||||||
{
|
{
|
||||||
select_query = typeid_cast<ASTSelectQuery *>(&*ast);
|
select_query = typeid_cast<ASTSelectQuery *>(&*ast);
|
||||||
@ -167,13 +142,13 @@ void ExpressionAnalyzer::createAliasesDict(ASTPtr & ast, int ignore_levels)
|
|||||||
if (ignore_levels > 0)
|
if (ignore_levels > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string * alias = tryGetAlias(ast);
|
String alias = ast->tryGetAlias();
|
||||||
if (alias && !alias->empty())
|
if (!alias.empty())
|
||||||
{
|
{
|
||||||
if (aliases.count(*alias) && ast->getTreeID() != aliases[*alias]->getTreeID())
|
if (aliases.count(alias) && ast->getTreeID() != aliases[alias]->getTreeID())
|
||||||
throw Exception("Different expressions with the same alias " + *alias, ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS);
|
throw Exception("Different expressions with the same alias " + alias, ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS);
|
||||||
|
|
||||||
aliases[*alias] = ast;
|
aliases[alias] = ast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,9 +193,9 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
|||||||
ASTPtr initial_ast = ast;
|
ASTPtr initial_ast = ast;
|
||||||
current_asts.insert(initial_ast);
|
current_asts.insert(initial_ast);
|
||||||
|
|
||||||
std::string * my_alias = tryGetAlias(ast);
|
String my_alias = ast->tryGetAlias();
|
||||||
if (my_alias && !my_alias->empty())
|
if (!my_alias.empty())
|
||||||
current_alias = *my_alias;
|
current_alias = my_alias;
|
||||||
|
|
||||||
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
@ -256,11 +231,11 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
|||||||
/// Заменим его на соответствующий узел дерева.
|
/// Заменим его на соответствующий узел дерева.
|
||||||
if (current_asts.count(jt->second))
|
if (current_asts.count(jt->second))
|
||||||
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
||||||
if (my_alias && !my_alias->empty() && *my_alias != jt->second->getAlias())
|
if (!my_alias.empty() && my_alias != jt->second->getAliasOrColumnName())
|
||||||
{
|
{
|
||||||
/// В конструкции вроде "a AS b", где a - алиас, нужно перевесить алиас b на результат подстановки алиаса a.
|
/// В конструкции вроде "a AS b", где a - алиас, нужно перевесить алиас b на результат подстановки алиаса a.
|
||||||
ast = jt->second->clone();
|
ast = jt->second->clone();
|
||||||
setAlias(ast, *my_alias);
|
ast->setAlias(my_alias);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -800,7 +775,7 @@ void ExpressionAnalyzer::getArrayJoinedColumns()
|
|||||||
ASTPtr ast = array_join_asts [i];
|
ASTPtr ast = array_join_asts [i];
|
||||||
|
|
||||||
String nested_table_name = ast->getColumnName();
|
String nested_table_name = ast->getColumnName();
|
||||||
String nested_table_alias = ast->getAlias();
|
String nested_table_alias = ast->getAliasOrColumnName();
|
||||||
if (nested_table_alias == nested_table_name && !typeid_cast<ASTIdentifier *>(&*ast))
|
if (nested_table_alias == nested_table_name && !typeid_cast<ASTIdentifier *>(&*ast))
|
||||||
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);
|
||||||
|
|
||||||
@ -824,7 +799,7 @@ void ExpressionAnalyzer::getArrayJoinedColumns()
|
|||||||
{
|
{
|
||||||
ASTPtr expr = select_query->array_join_expression_list->children[0];
|
ASTPtr expr = select_query->array_join_expression_list->children[0];
|
||||||
String source_name = expr->getColumnName();
|
String source_name = expr->getColumnName();
|
||||||
String result_name = expr->getAlias();
|
String result_name = expr->getAliasOrColumnName();
|
||||||
|
|
||||||
/// Это массив.
|
/// Это массив.
|
||||||
if (!typeid_cast<ASTIdentifier *>(&*expr) || findColumn(source_name, columns) != columns.end())
|
if (!typeid_cast<ASTIdentifier *>(&*expr) || findColumn(source_name, columns) != columns.end())
|
||||||
@ -1428,7 +1403,7 @@ void ExpressionAnalyzer::appendProjectResult(DB::ExpressionActionsChain & chain,
|
|||||||
ASTs asts = select_query->select_expression_list->children;
|
ASTs asts = select_query->select_expression_list->children;
|
||||||
for (size_t i = 0; i < asts.size(); ++i)
|
for (size_t i = 0; i < asts.size(); ++i)
|
||||||
{
|
{
|
||||||
result_columns.push_back(NameWithAlias(asts[i]->getColumnName(), asts[i]->getAlias()));
|
result_columns.push_back(NameWithAlias(asts[i]->getColumnName(), asts[i]->getAliasOrColumnName()));
|
||||||
step.required_output.push_back(result_columns.back().second);
|
step.required_output.push_back(result_columns.back().second);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1460,7 +1435,7 @@ Block ExpressionAnalyzer::getSelectSampleBlock()
|
|||||||
ASTs asts = select_query->select_expression_list->children;
|
ASTs asts = select_query->select_expression_list->children;
|
||||||
for (size_t i = 0; i < asts.size(); ++i)
|
for (size_t i = 0; i < asts.size(); ++i)
|
||||||
{
|
{
|
||||||
result_columns.push_back(NameWithAlias(asts[i]->getColumnName(), asts[i]->getAlias()));
|
result_columns.push_back(NameWithAlias(asts[i]->getColumnName(), asts[i]->getAliasOrColumnName()));
|
||||||
getRootActionsImpl(asts[i], true, false, temp_actions);
|
getRootActionsImpl(asts[i], true, false, temp_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1509,7 +1484,7 @@ ExpressionActionsPtr ExpressionAnalyzer::getActions(bool project_result)
|
|||||||
std::string name = asts[i]->getColumnName();
|
std::string name = asts[i]->getColumnName();
|
||||||
std::string alias;
|
std::string alias;
|
||||||
if (project_result)
|
if (project_result)
|
||||||
alias = asts[i]->getAlias();
|
alias = asts[i]->getAliasOrColumnName();
|
||||||
else
|
else
|
||||||
alias = name;
|
alias = name;
|
||||||
result_columns.push_back(NameWithAlias(name, alias));
|
result_columns.push_back(NameWithAlias(name, alias));
|
||||||
@ -1578,7 +1553,7 @@ void ExpressionAnalyzer::removeUnusedColumns()
|
|||||||
getRequiredColumnsImpl(expressions[i], required, empty, empty, empty);
|
getRequiredColumnsImpl(expressions[i], required, empty, empty, empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
ignored.insert(expressions[i]->getAlias());
|
ignored.insert(expressions[i]->getAliasOrColumnName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1663,7 +1638,7 @@ void ExpressionAnalyzer::collectJoinedColumns(NameSet & joined_columns, NamesAnd
|
|||||||
if (!join_key_names_left_set.insert(keys.children[i]->getColumnName()).second)
|
if (!join_key_names_left_set.insert(keys.children[i]->getColumnName()).second)
|
||||||
throw Exception("Duplicate column in USING list", ErrorCodes::DUPLICATE_COLUMN);
|
throw Exception("Duplicate column in USING list", ErrorCodes::DUPLICATE_COLUMN);
|
||||||
|
|
||||||
if (!join_key_names_right_set.insert(keys.children[i]->getAlias()).second)
|
if (!join_key_names_right_set.insert(keys.children[i]->getAliasOrColumnName()).second)
|
||||||
throw Exception("Duplicate column in USING list", ErrorCodes::DUPLICATE_COLUMN);
|
throw Exception("Duplicate column in USING list", ErrorCodes::DUPLICATE_COLUMN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user