dbms: add support for drop nested columns [#METR-10550]

This commit is contained in:
Pavel Kartavyy 2014-04-02 22:53:30 +04:00
parent fa7cba6de4
commit 765d0740f4
2 changed files with 68 additions and 8 deletions

View File

@ -5,6 +5,7 @@
namespace DB
{
class ASTIdentifier;
/** Позволяет добавить или удалить столбец в таблице.
*/
@ -16,6 +17,8 @@ public:
void execute();
private:
void dropColumnFromAST(const ASTIdentifier & drop_column, ASTs & columns);
ASTPtr query_ptr;
Context context;

View File

@ -39,6 +39,65 @@ static bool namesEqualIgnoreAfterDot(const String & name_without_dot, const ASTP
return (name_without_dot == name_type.name || name_with_dot == name_type.name.substr(0, name_with_dot.length()));
}
void InterpreterAlterQuery::dropColumnFromAST(const ASTIdentifier & drop_column, ASTs & columns)
{
Exception e("Wrong column name. Cannot find column " + drop_column.name + " to drop", DB::ErrorCodes::ILLEGAL_COLUMN);
ASTs::iterator drop_it;
size_t dot_pos = drop_column.name.find('.');
/// случай удаления nested столбца
if (dot_pos != std::string::npos)
{
/// в Distributed таблицах столбцы имеют название "nested.column"
drop_it = std::find_if(columns.begin(), columns.end(), boost::bind(namesEqual, drop_column.name, _1));
if (drop_it != columns.end())
columns.erase(drop_it);
else
{
try
{
/// в MergeTree таблицах есть ASTFunction "nested"
/// в аргументах которой записаны столбцы
ASTs::iterator nested_it;
std::string nested_base_name = drop_column.name.substr(0, dot_pos);
nested_it = std::find_if(columns.begin(), columns.end(), boost::bind(namesEqual, nested_base_name, _1));
if (nested_it == columns.end())
throw e;
if ((**nested_it).children.size() != 1)
throw e;
ASTFunction & f = dynamic_cast<ASTFunction &>(*(**nested_it).children.back());
if (f.name != "Nested")
throw e;
ASTs & nested_columns = dynamic_cast<ASTExpressionList &>(*f.arguments).children;
drop_it = std::find_if(nested_columns.begin(), nested_columns.end(), boost::bind(namesEqual, drop_column.name.substr(dot_pos + 1), _1));
if (drop_it == nested_columns.end())
throw e;
else
nested_columns.erase(drop_it);
if (nested_columns.empty())
columns.erase(nested_it);
}
catch (std::bad_cast & bad_cast_err)
{
throw e;
}
}
}
else
{
drop_it = std::find_if(columns.begin(), columns.end(), boost::bind(namesEqual, drop_column.name, _1));
if (drop_it == columns.end())
throw e;
else
columns.erase(drop_it);
}
}
void InterpreterAlterQuery::execute()
{
ASTAlterQuery & alter = dynamic_cast<ASTAlterQuery &>(*query_ptr);
@ -62,7 +121,10 @@ void InterpreterAlterQuery::execute()
ASTs & columns = dynamic_cast<ASTExpressionList &>(*attach.columns).children;
/// Различные проверки, на возможность выполнения запроса
ASTs columns_copy = columns;
ASTs columns_copy;
for (const auto & ast : columns)
columns_copy.push_back(ast->clone());
IdentifierNameSet identifier_names;
attach.storage->collectIdentifierNames(identifier_names);
for (ASTAlterQuery::ParameterContainer::const_iterator alter_it = alter.parameters.begin();
@ -101,11 +163,7 @@ void InterpreterAlterQuery::execute()
if (identifier_names.find(drop_column.name) != identifier_names.end())
throw Exception("Cannot drop key column", DB::ErrorCodes::ILLEGAL_COLUMN);
ASTs::iterator drop_it = std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, drop_column.name, _1));
if (drop_it == columns_copy.end())
throw Exception("Wrong column name. Cannot find column " + drop_column.name +" to drop", DB::ErrorCodes::ILLEGAL_COLUMN);
else
columns_copy.erase(drop_it);
dropColumnFromAST(drop_column, columns_copy);
}
else if (params.type == ASTAlterQuery::MODIFY)
{
@ -172,8 +230,7 @@ void InterpreterAlterQuery::execute()
else if (params.type == ASTAlterQuery::DROP)
{
const ASTIdentifier & drop_column = dynamic_cast <const ASTIdentifier &>(*params.column);
ASTs::iterator drop_it = std::find_if(columns.begin(), columns.end(), boost::bind(namesEqual, drop_column.name, _1));
columns.erase(drop_it);
dropColumnFromAST(drop_column, columns);
}
else if (params.type == ASTAlterQuery::MODIFY)
{