#include #include #include #include #include #include #include #include #include #include #include #include #include "Common/Exception.h" namespace DB { namespace ErrorCodes { extern const int INCORRECT_QUERY; extern const int LOGICAL_ERROR; } namespace { using ReplaceAliasToExprVisitor = InDepthNodeVisitor; } IndexDescription::IndexDescription(const IndexDescription & other) : definition_ast(other.definition_ast ? other.definition_ast->clone() : nullptr) , expression_list_ast(other.expression_list_ast ? other.expression_list_ast->clone() : nullptr) , name(other.name) , type(other.type) , arguments(other.arguments) , column_names(other.column_names) , data_types(other.data_types) , sample_block(other.sample_block) , granularity(other.granularity) { if (other.expression) expression = other.expression->clone(); } IndexDescription & IndexDescription::operator=(const IndexDescription & other) { if (&other == this) return *this; 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(); else expression_list_ast.reset(); name = other.name; type = other.type; if (other.expression) expression = other.expression->clone(); else expression.reset(); arguments = other.arguments; column_names = other.column_names; data_types = other.data_types; sample_block = other.sample_block; granularity = other.granularity; return *this; } IndexDescription IndexDescription::getIndexFromAST(const ASTPtr & definition_ast, const ColumnsDescription & columns, ContextPtr context) { const auto * index_definition = definition_ast->as(); if (!index_definition) throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot create skip index from non ASTIndexDeclaration AST"); if (index_definition->name.empty()) throw Exception(ErrorCodes::INCORRECT_QUERY, "Skip index must have name in definition."); if (!index_definition->type) throw Exception(ErrorCodes::INCORRECT_QUERY, "TYPE is required for index"); if (index_definition->type->parameters && !index_definition->type->parameters->children.empty()) throw Exception(ErrorCodes::INCORRECT_QUERY, "Index type cannot have parameters"); IndexDescription result; result.definition_ast = index_definition->clone(); result.name = index_definition->name; result.type = Poco::toLower(index_definition->type->name); result.granularity = index_definition->granularity; ASTPtr expr_list; if (index_definition->expr) { expr_list = extractKeyExpressionList(index_definition->expr->clone()); ReplaceAliasToExprVisitor::Data data{columns}; ReplaceAliasToExprVisitor{data}.visit(expr_list); result.expression_list_ast = expr_list->clone(); } else { throw Exception(ErrorCodes::LOGICAL_ERROR, "Expression is not set"); } auto syntax = TreeRewriter(context).analyze(expr_list, columns.getAllPhysical()); result.expression = ExpressionAnalyzer(expr_list, syntax, context).getActions(true); result.sample_block = result.expression->getSampleBlock(); for (auto & elem : result.sample_block) { if (!elem.column) elem.column = elem.type->createColumn(); result.column_names.push_back(elem.name); result.data_types.push_back(elem.type); } const auto & definition_arguments = index_definition->type->arguments; if (definition_arguments) { for (size_t i = 0; i < definition_arguments->children.size(); ++i) { const auto * argument = definition_arguments->children[i]->as(); if (!argument) throw Exception(ErrorCodes::INCORRECT_QUERY, "Only literals can be skip index arguments"); result.arguments.emplace_back(argument->value); } } return result; } void IndexDescription::recalculateWithNewColumns(const ColumnsDescription & new_columns, ContextPtr context) { *this = getIndexFromAST(definition_ast, new_columns, context); } bool IndicesDescription::has(const String & name) const { for (const auto & index : *this) if (index.name == name) return true; return false; } String IndicesDescription::toString() const { if (empty()) return {}; ASTExpressionList list; for (const auto & index : *this) list.children.push_back(index.definition_ast); return serializeAST(list); } IndicesDescription IndicesDescription::parse(const String & str, const ColumnsDescription & columns, ContextPtr context) { IndicesDescription result; if (str.empty()) return result; ParserIndexDeclarationList parser; ASTPtr list = parseQuery(parser, str, 0, DBMS_DEFAULT_MAX_PARSER_DEPTH); for (const auto & index : list->children) result.emplace_back(IndexDescription::getIndexFromAST(index, columns, context)); return result; } ExpressionActionsPtr IndicesDescription::getSingleExpressionForIndices(const ColumnsDescription & columns, ContextPtr context) const { ASTPtr combined_expr_list = std::make_shared(); for (const auto & index : *this) for (const auto & index_expr : index.expression_list_ast->children) combined_expr_list->children.push_back(index_expr->clone()); auto syntax_result = TreeRewriter(context).analyze(combined_expr_list, columns.getAllPhysical()); return ExpressionAnalyzer(combined_expr_list, syntax_result, context).getActions(false); } Names IndicesDescription::getAllRegisteredNames() const { Names result; for (const auto & index : *this) { result.emplace_back(index.name); } return result; } }