From eac9f3c33713a3e85e78a16c9babf2fbfb75cbb5 Mon Sep 17 00:00:00 2001 From: Michael Kolupaev Date: Mon, 11 Feb 2013 17:30:09 +0000 Subject: [PATCH] clickhouse: fixed some alias issues [#CONV-2944]. --- dbms/include/DB/Core/ErrorCodes.h | 3 +- dbms/src/Interpreters/Expression.cpp | 68 ++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/dbms/include/DB/Core/ErrorCodes.h b/dbms/include/DB/Core/ErrorCodes.h index 8adf18aedbe..2285599bbde 100644 --- a/dbms/include/DB/Core/ErrorCodes.h +++ b/dbms/include/DB/Core/ErrorCodes.h @@ -184,7 +184,8 @@ namespace ErrorCodes NEGATIVE_REFCOUNT, CHUNK_NOT_FOUND, DUPLICATE_CHUNK_NAME, - NO_SUCH_TABLE, + MULTIPLE_ALIASES_FOR_EXPRESSION, + MULTIPLE_EXPRESSIONS_FOR_ALIAS, POCO_EXCEPTION = 1000, STD_EXCEPTION, diff --git a/dbms/src/Interpreters/Expression.cpp b/dbms/src/Interpreters/Expression.cpp index 2475054925d..63a6379b827 100644 --- a/dbms/src/Interpreters/Expression.cpp +++ b/dbms/src/Interpreters/Expression.cpp @@ -32,6 +32,27 @@ NamesAndTypesList::const_iterator Expression::findColumn(const String & name) } +static std::string * GetAlias(ASTPtr & ast) +{ + if (ASTFunction * node = dynamic_cast(&*ast)) + { + return &node->alias; + } + else if (ASTIdentifier * node = dynamic_cast(&*ast)) + { + return &node->alias; + } + else if (ASTLiteral * node = dynamic_cast(&*ast)) + { + return &node->alias; + } + else + { + return NULL; + } +} + + void Expression::createAliasesDict(ASTPtr & ast) { /// Обход снизу-вверх. Не опускаемся в подзапросы. @@ -39,20 +60,17 @@ void Expression::createAliasesDict(ASTPtr & ast) if (!dynamic_cast(&**it)) createAliasesDict(*it); - if (ASTFunction * node = dynamic_cast(&*ast)) + std::string * alias = GetAlias(ast); + if (alias) { - if (!node->alias.empty()) - aliases[node->alias] = ast; - } - else if (ASTIdentifier * node = dynamic_cast(&*ast)) - { - if (!node->alias.empty()) - aliases[node->alias] = ast; - } - else if (ASTLiteral * node = dynamic_cast(&*ast)) - { - if (!node->alias.empty()) - aliases[node->alias] = ast; + if (aliases.count(*alias)) + { + throw Exception("Multiple expressions with the same alias", ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS); + } + else + { + aliases[*alias] = ast; + } } } @@ -245,9 +263,33 @@ void Expression::glueTreeImpl(ASTPtr ast, Subtrees & subtrees) { String tree_id = (*it)->getTreeID(); if (subtrees.end() == subtrees.find(tree_id)) + { subtrees[tree_id] = *it; + } else + { + /// Перед заменой поддерева запомним алиас. + std::string * alias_ptr = GetAlias(*it); + std::string initial_alias; + if (alias_ptr) + initial_alias = *alias_ptr; + *it = subtrees[tree_id]; + + /// Объединим два алиаса. + alias_ptr = GetAlias(*it); + if (alias_ptr) + { + if (alias_ptr->empty()) + { + *alias_ptr = initial_alias; + } + else if (!initial_alias.empty()) + { + throw Exception("Multiple aliases for the same expression", ErrorCodes::MULTIPLE_ALIASES_FOR_EXPRESSION); + } + } + } } } }