ClickHouse/src/Storages/KeyDescription.cpp

157 lines
4.9 KiB
C++
Raw Normal View History

2020-06-05 17:29:40 +00:00
#include <Storages/KeyDescription.h>
#include <Functions/IFunction.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTFunction.h>
2020-06-05 17:29:40 +00:00
#include <Interpreters/ExpressionActions.h>
#include <Interpreters/ExpressionAnalyzer.h>
#include <Interpreters/TreeRewriter.h>
2020-06-05 17:29:40 +00:00
#include <Storages/extractKeyExpressionList.h>
#include <Common/quoteString.h>
2020-06-05 17:29:40 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
extern const int DATA_TYPE_CANNOT_BE_USED_IN_KEY;
}
2020-06-05 17:29:40 +00:00
KeyDescription::KeyDescription(const KeyDescription & other)
: definition_ast(other.definition_ast ? other.definition_ast->clone() : nullptr)
, expression_list_ast(other.expression_list_ast ? other.expression_list_ast->clone() : nullptr)
, sample_block(other.sample_block)
, column_names(other.column_names)
, data_types(other.data_types)
, additional_column(other.additional_column)
2020-06-05 17:29:40 +00:00
{
2020-06-12 14:32:47 +00:00
if (other.expression)
2020-11-03 11:28:28 +00:00
expression = other.expression->clone();
2020-06-05 17:29:40 +00:00
}
KeyDescription & KeyDescription::operator=(const KeyDescription & other)
{
2020-06-09 17:42:04 +00:00
if (&other == this)
return *this;
2020-06-05 17:29:40 +00:00
if (other.definition_ast)
definition_ast = other.definition_ast->clone();
else
definition_ast.reset();
if (other.expression_list_ast)
expression_list_ast = other.expression_list_ast->clone();
2020-06-12 14:32:47 +00:00
else
expression_list_ast.reset();
if (other.expression)
2020-11-03 11:28:28 +00:00
expression = other.expression->clone();
2020-06-12 14:32:47 +00:00
else
expression.reset();
2020-06-05 17:29:40 +00:00
sample_block = other.sample_block;
column_names = other.column_names;
data_types = other.data_types;
/// additional_column is constant property It should never be lost.
if (additional_column.has_value() && !other.additional_column.has_value())
2020-08-08 00:47:03 +00:00
throw Exception("Wrong key assignment, losing additional_column", ErrorCodes::LOGICAL_ERROR);
additional_column = other.additional_column;
2020-06-05 17:29:40 +00:00
return *this;
}
void KeyDescription::recalculateWithNewAST(
const ASTPtr & new_ast,
const ColumnsDescription & columns,
ContextPtr context)
{
*this = getSortingKeyFromAST(new_ast, columns, context, additional_column);
}
void KeyDescription::recalculateWithNewColumns(
const ColumnsDescription & new_columns,
ContextPtr context)
{
*this = getSortingKeyFromAST(definition_ast, new_columns, context, additional_column);
}
2020-06-10 11:27:16 +00:00
KeyDescription KeyDescription::getKeyFromAST(
const ASTPtr & definition_ast,
const ColumnsDescription & columns,
ContextPtr context)
{
return getSortingKeyFromAST(definition_ast, columns, context, {});
}
bool KeyDescription::moduloToModuloLegacyRecursive(ASTPtr node_expr)
2021-05-20 12:36:18 +00:00
{
if (!node_expr)
return false;
2021-05-20 12:36:18 +00:00
auto * function_expr = node_expr->as<ASTFunction>();
bool modulo_in_ast = false;
2021-05-20 12:36:18 +00:00
if (function_expr)
{
if (function_expr->name == "modulo")
{
function_expr->name = "moduloLegacy";
modulo_in_ast = true;
2021-05-20 12:36:18 +00:00
}
if (function_expr->arguments)
{
auto children = function_expr->arguments->children;
for (const auto & child : children)
modulo_in_ast |= moduloToModuloLegacyRecursive(child);
2021-05-20 12:36:18 +00:00
}
}
return modulo_in_ast;
2021-05-20 12:36:18 +00:00
}
KeyDescription KeyDescription::getSortingKeyFromAST(
2020-06-10 11:27:16 +00:00
const ASTPtr & definition_ast,
const ColumnsDescription & columns,
ContextPtr context,
const std::optional<String> & additional_column)
2020-06-05 17:29:40 +00:00
{
KeyDescription result;
result.definition_ast = definition_ast;
result.expression_list_ast = extractKeyExpressionList(definition_ast);
2020-06-05 17:29:40 +00:00
if (additional_column)
{
result.additional_column = additional_column;
ASTPtr column_identifier = std::make_shared<ASTIdentifier>(*additional_column);
result.expression_list_ast->children.push_back(column_identifier);
}
2020-06-05 17:29:40 +00:00
const auto & children = result.expression_list_ast->children;
for (const auto & child : children)
result.column_names.emplace_back(child->getColumnName());
{
auto expr = result.expression_list_ast->clone();
auto syntax_result = TreeRewriter(context).analyze(expr, columns.getAllPhysical());
2020-06-08 14:18:38 +00:00
/// In expression we also need to store source columns
result.expression = ExpressionAnalyzer(expr, syntax_result, context).getActions(false);
/// In sample block we use just key columns
result.sample_block = ExpressionAnalyzer(expr, syntax_result, context).getActions(true)->getSampleBlock();
2020-06-05 17:29:40 +00:00
}
for (size_t i = 0; i < result.sample_block.columns(); ++i)
{
2020-06-05 17:29:40 +00:00
result.data_types.emplace_back(result.sample_block.getByPosition(i).type);
if (!result.data_types.back()->isComparable())
throw Exception(ErrorCodes::DATA_TYPE_CANNOT_BE_USED_IN_KEY,
"Column {} with type {} is not allowed in key expression, it's not comparable",
backQuote(result.sample_block.getByPosition(i).name), result.data_types.back()->getName());
}
2020-06-05 17:29:40 +00:00
return result;
}
}