ISSUE-4006 add alter query parser

This commit is contained in:
zhang2014 2020-07-13 02:23:42 +08:00
parent 3dda4d7dfb
commit 04c2ab5ab9
12 changed files with 401 additions and 54 deletions

View File

@ -5,6 +5,7 @@
#include <Parsers/CommonParsers.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/MySQL/ASTDeclareOption.h>
#include <Parsers/MySQL/ASTDeclareTableOptions.h>
namespace DB
@ -13,12 +14,37 @@ namespace DB
namespace MySQLParser
{
ASTPtr ASTAlterCommand::clone() const
{
auto res = std::make_shared<ASTAlterCommand>(*this);
res->children.clear();
if (index_decl)
res->set(res->index_decl, index_decl->clone());
if (default_expression)
res->set(res->default_expression, default_expression->clone());
if (additional_columns)
res->set(res->additional_columns, additional_columns->clone());
if (order_by_columns)
res->set(res->order_by_columns, additional_columns->clone());
if (properties)
res->set(res->properties, properties->clone());
return res;
}
bool ParserAlterCommand::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
{
ParserKeyword k_add("ADD");
ParserKeyword k_drop("DROP");
ParserKeyword k_alter("ALTER");
ParserKeyword k_rename("RENAME");
ParserKeyword k_modify("MODIFY");
ParserKeyword k_change("CHANGE");
if (k_add.ignore(pos, expected))
return parseAddCommand(pos, node, expected);
@ -28,13 +54,12 @@ bool ParserAlterCommand::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &
return parseAlterCommand(pos, node, expected);
else if (k_rename.ignore(pos, expected))
return parseRenameCommand(pos, node, expected);
else if (k_modify.ignore(pos, expected))
return parseModifyCommand(pos, node, expected);
else if (k_change.ignore(pos, expected))
return parseModifyCommand(pos, node, expected, true);
else
return parseOtherCommand(pos, node, expected);
// | MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name]
// | CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST | AFTER col_name]
}
bool ParserAlterCommand::parseAddCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected)
@ -273,45 +298,89 @@ bool ParserAlterCommand::parseRenameCommand(IParser::Pos & pos, ASTPtr & node, E
bool ParserAlterCommand::parseOtherCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected)
{
// | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
// | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]
// | LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
// | ORDER BY col_name [, col_name] ...
auto alter_command = std::make_shared<ASTAlterCommand>();
if (ParserKeyword("FORCE").ignore(pos, expected))
if (ParserKeyword("ORDER BY").ignore(pos, expected))
{
/// FORCE
}
else if (ParserKeyword("ALGORITHM").ignore(pos, expected))
{
/// ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY}
}
else if (ParserKeyword("WITH").ignore(pos, expected) || ParserKeyword("WITHOUT").ignore(pos, expected))
{
/// {WITHOUT | WITH} VALIDATION
}
else if (ParserKeyword("IMPORT").ignore(pos, expected) || ParserKeyword("DISCARD").ignore(pos, expected))
{
/// {DISCARD | IMPORT} TABLESPACE
}
else if (ParserKeyword("ENABLE").ignore(pos, expected) || ParserKeyword("DISABLE").ignore(pos, expected))
{
/// {DISABLE | ENABLE} KEYS
/// ORDER BY col_name [, col_name] ...
ASTPtr columns;
ParserList columns_p(std::make_unique<ParserIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma));
if (!columns_p.parse(pos, columns, expected))
return false;
alter_command->type = ASTAlterCommand::ORDER_BY;
alter_command->set(alter_command->order_by_columns, columns);
}
else
{
ASTPtr table_options;
ParserDeclareOption options_p{
{
OptionDescribe("FORCE", "force", std::make_shared<ParserAlwaysTrue>()),
OptionDescribe("ALGORITHM", "algorithm", std::make_shared<ParserIdentifier>()),
OptionDescribe("WITH VALIDATION", "validation", std::make_shared<ParserAlwaysTrue>()),
OptionDescribe("WITHOUT VALIDATION", "validation", std::make_shared<ParserAlwaysFalse>()),
OptionDescribe("IMPORT TABLESPACE", "import_tablespace", std::make_shared<ParserAlwaysTrue>()),
OptionDescribe("DISCARD TABLESPACE", "import_tablespace", std::make_shared<ParserAlwaysFalse>()),
OptionDescribe("ENABLE KEYS", "enable_keys", std::make_shared<ParserAlwaysTrue>()),
OptionDescribe("DISABLE KEYS", "enable_keys", std::make_shared<ParserAlwaysFalse>()),
/// TODO: with collate
OptionDescribe("CONVERT TO CHARACTER SET", "charset", std::make_shared<ParserCharsetName>()),
OptionDescribe("CHARACTER SET", "charset", std::make_shared<ParserCharsetName>()),
OptionDescribe("DEFAULT CHARACTER SET", "charset", std::make_shared<ParserCharsetName>()),
OptionDescribe("LOCK", "lock", std::make_shared<ParserIdentifier>())
}
};
ASTPtr properties_options;
ParserDeclareTableOptions table_options_p;
if (!table_options_p.parse(pos, table_options, expected))
if (!options_p.parse(pos, properties_options, expected) && !table_options_p.parse(pos, properties_options, expected))
return false;
/// set.
alter_command->type = ASTAlterCommand::MODIFY_PROPERTIES;
alter_command->set(alter_command->properties, properties_options);
}
return false;
}
node = alter_command;
return true;
}
bool ParserAlterCommand::parseModifyCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected, bool exists_old_column_name)
{
ASTPtr old_column_name;
auto alter_command = std::make_shared<ASTAlterCommand>();
ParserKeyword("COLUMN").ignore(pos, expected);
if (exists_old_column_name && !ParserIdentifier().parse(pos, old_column_name, expected))
return false;
ASTPtr additional_column;
if (!ParserDeclareColumn().parse(pos, additional_column, expected))
return false;
if (ParserKeyword("FIRST").ignore(pos, expected))
alter_command->first = true;
else if (ParserKeyword("AFTER").ignore(pos, expected))
{
ASTPtr after_column;
ParserIdentifier identifier_p;
if (!identifier_p.parse(pos, after_column, expected))
return false;
alter_command->column_name = getIdentifierName(after_column);
}
node = alter_command;
alter_command->type = ASTAlterCommand::MODIFY_COLUMN;
alter_command->set(alter_command->additional_columns, std::make_shared<ASTExpressionList>());
alter_command->additional_columns->children.emplace_back(additional_column);
if (exists_old_column_name)
alter_command->old_name = getIdentifierName(old_column_name);
return true;
}
}
}

View File

@ -31,9 +31,9 @@ public:
MODIFY_CHECK,
MODIFY_COLUMN,
MODIFY_TABLE_OPTIONS,
MODIFY_INDEX_VISIBLE,
MODIFY_COLUMN_DEFAULT,
MODIFY_PROPERTIES,
ORDER_BY,
@ -50,6 +50,8 @@ public:
/// For ADD COLUMN
ASTExpressionList * additional_columns;
/// For ORDER BY
ASTExpressionList * order_by_columns;
bool first = false;
bool index_visible = false;
@ -60,6 +62,12 @@ public:
String index_name;
String column_name;
String constraint_name;
IAST * properties;
ASTPtr clone() const override;
String getID(char delim) const override { return "AlterCommand" + (delim + std::to_string(static_cast<int>(type))); }
};
class ParserAlterCommand : public IParserBase
@ -77,6 +85,8 @@ protected:
bool parseRenameCommand(Pos & pos, ASTPtr & node, Expected & expected);
bool parseModifyCommand(Pos & pos, ASTPtr & node, Expected & expected, bool exists_old_column_name = false);
bool parseOtherCommand(Pos & pos, ASTPtr & node, Expected & expected);
};

View File

@ -1,11 +1,12 @@
#include <Parsers/MySQL/ASTAlterQuery.h>
#include <Interpreters/StorageID.h>
#include <Common/quoteString.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/CommonParsers.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ExpressionListParsers.h>
#include <Common/quoteString.h>
#include <Parsers/MySQL/ASTAlterCommand.h>
namespace DB
{
@ -27,7 +28,7 @@ ASTPtr ASTAlterQuery::clone() const
return res;
}
void ASTAlterQuery::formatImpl(const IAST::FormatSettings & settings, IAST::FormatState & state, IAST::FormatStateStacked frame) const
/*void ASTAlterQuery::formatImpl(const IAST::FormatSettings & settings, IAST::FormatState & state, IAST::FormatStateStacked frame) const
{
frame.need_parens = false;
@ -50,7 +51,7 @@ void ASTAlterQuery::formatImpl(const IAST::FormatSettings & settings, IAST::Form
frame_nested.need_parens = false;
++frame_nested.indent;
// static_cast<IAST *>(command_list)->formatImpl(settings, state, frame_nested);
}
}*/
bool ParserAlterQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
{

View File

@ -22,8 +22,8 @@ public:
String getID(char delim) const override { return "AlterQuery" + (delim + database) + delim + table; }
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
/*protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;*/
};
class ParserAlterQuery : public IParserBase

View File

@ -49,8 +49,7 @@ bool ParserDeclareColumn::parseImpl(Pos & pos, ASTPtr & node, Expected & expecte
if (!ParserDataType().parse(pos, column_data_type, expected))
return false;
if (!parseColumnDeclareOptions(pos, column_options, expected))
return false;
parseColumnDeclareOptions(pos, column_options, expected);
auto declare_column = std::make_shared<ASTDeclareColumn>();
declare_column->name = getIdentifierName(column_name);
@ -68,7 +67,7 @@ bool ParserDeclareColumn::parseImpl(Pos & pos, ASTPtr & node, Expected & expecte
}
bool ParserDeclareColumn::parseColumnDeclareOptions(IParser::Pos & pos, ASTPtr & node, Expected & expected)
{
ParserDeclareOption p_non_generate_options{
ParserDeclareOptions p_non_generate_options{
{
OptionDescribe("ZEROFILL", "zero_fill", std::make_unique<ParserAlwaysTrue>()),
OptionDescribe("NULL", "is_null", std::make_unique<ParserAlwaysTrue>()),

View File

@ -66,7 +66,7 @@ bool ParserDeclareIndex::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &
ASTPtr declare_reference;
ParserIndexColumn p_expression;
ParserDeclareOption p_index_options{
ParserDeclareOptions p_index_options{
{
OptionDescribe("KEY_BLOCK_SIZE", "key_block_size", std::make_unique<ParserLiteral>()),
OptionDescribe("USING", "index_type", std::make_unique<ParserIdentifier>()),

View File

@ -11,7 +11,8 @@ namespace DB
namespace MySQLParser
{
bool ParserDeclareOption::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
template <bool recursive_>
bool ParserDeclareOptionImpl<recursive_>::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
std::unordered_map<String, ASTPtr> changes;
std::unordered_map<String, std::shared_ptr<IParser>> usage_parsers_cached;
@ -26,7 +27,7 @@ bool ParserDeclareOption::parseImpl(Pos & pos, ASTPtr & node, Expected & expecte
return iterator->second;
};
while (true)
do
{
ASTPtr value;
bool found{false};
@ -57,9 +58,7 @@ bool ParserDeclareOption::parseImpl(Pos & pos, ASTPtr & node, Expected & expecte
if (!found)
break;
// ParserToken{TokenType::Comma}.ignore(pos, expected);
}
} while (recursive);
if (!changes.empty())
{
@ -69,7 +68,7 @@ bool ParserDeclareOption::parseImpl(Pos & pos, ASTPtr & node, Expected & expecte
node = options_declare;
}
return true;
return !changes.empty();
}
ASTPtr ASTDeclareOptions::clone() const
@ -135,6 +134,10 @@ bool ParserCharsetName::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &)
return false;
}
template class ParserDeclareOptionImpl<true>;
template class ParserDeclareOptionImpl<false>;
}
}

View File

@ -58,18 +58,24 @@ protected:
bool parseImpl(Pos & pos, ASTPtr & node, Expected &) override;
};
class ParserDeclareOption : public IParserBase
template <bool recursive_>
class ParserDeclareOptionImpl : public IParserBase
{
protected:
bool recursive = recursive_;
std::vector<OptionDescribe> options_collection;
const char * getName() const override { return "option declaration"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
public:
ParserDeclareOption(const std::vector<OptionDescribe> & options_collection_) : options_collection(options_collection_) {}
ParserDeclareOptionImpl(const std::vector<OptionDescribe> & options_collection_) : options_collection(options_collection_) {}
};
using ParserDeclareOption = ParserDeclareOptionImpl<false>;
using ParserDeclareOptions = ParserDeclareOptionImpl<true>;
}

View File

@ -75,7 +75,7 @@ bool ParserDeclarePartition::parseImpl(IParser::Pos & pos, ASTPtr & node, Expect
}
}
if (!ParserDeclareOption{
if (!ParserDeclareOptions{
{
OptionDescribe("ENGINE", "engine", std::make_shared<ParserIdentifier>()),
OptionDescribe("STORAGE ENGINE", "engine", std::make_shared<ParserIdentifier>()),

View File

@ -23,7 +23,7 @@ bool ParserDeclareSubPartition::parseImpl(Pos & pos, ASTPtr & node, Expected & e
if (!p_identifier.parse(pos, logical_name, expected))
return false;
if (!ParserDeclareOption{
if (!ParserDeclareOptions{
{
OptionDescribe("ENGINE", "engine", std::make_shared<ParserIdentifier>()),
OptionDescribe("STORAGE ENGINE", "engine", std::make_shared<ParserIdentifier>()),

View File

@ -45,6 +45,7 @@ protected:
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
ParserIdentifier p_identifier;
if (!p_identifier.parse(pos, node, expected))
return false;
@ -63,7 +64,7 @@ protected:
bool ParserDeclareTableOptions::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
{
return ParserDeclareOption{
return ParserDeclareOptions{
{
OptionDescribe("AUTO_INCREMENT", "auto_increment", std::make_shared<ParserLiteral>()),
OptionDescribe("AVG_ROW_LENGTH", "avg_row_length", std::make_shared<ParserLiteral>()),

View File

@ -0,0 +1,258 @@
#include <gtest/gtest.h>
#include <Parsers/parseQuery.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/MySQL/ASTAlterCommand.h>
#include <Parsers/MySQL/ASTDeclareOption.h>
using namespace DB;
using namespace DB::MySQLParser;
ASTPtr tryParserQuery(IParser & parser, const String & query)
{
return parseQuery(parser, query.data(), query.data() + query.size(), "", 0, 0);
}
TEST(ParserAlterCommand, AddAlterCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "ADD column_name INT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::ADD_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
ast = tryParserQuery(alter_p, "ADD COLUMN column_name INT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::ADD_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
ast = tryParserQuery(alter_p, "ADD (column_name INT)");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::ADD_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
ast = tryParserQuery(alter_p, "ADD COLUMN (column_name INT, column_name_1 INT)");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::ADD_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 2);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[1]->as<ASTDeclareColumn>()->name, "column_name_1");
ast = tryParserQuery(alter_p, "ADD INDEX (col_01, col_02(100), col_03 DESC) KEY_BLOCK_SIZE 3");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::ADD_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_decl->index_columns->children.size(), 3);
EXPECT_EQ(getIdentifierName(ast->as<ASTAlterCommand>()->index_decl->index_columns->children[0]), "col_01");
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_decl->index_columns->children[1]->as<ASTFunction>()->name, "col_02");
EXPECT_EQ(getIdentifierName(ast->as<ASTAlterCommand>()->index_decl->index_columns->children[2]), "col_03");
}
TEST(ParserAlterCommand, DropAlterCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "DROP CHECK constraint_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_CHECK);
EXPECT_EQ(ast->as<ASTAlterCommand>()->constraint_name, "constraint_name");
ast = tryParserQuery(alter_p, "DROP CONSTRAINT constraint_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_CHECK);
EXPECT_EQ(ast->as<ASTAlterCommand>()->constraint_name, "constraint_name");
ast = tryParserQuery(alter_p, "DROP KEY index_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_type, "KEY");
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "index_name");
ast = tryParserQuery(alter_p, "DROP INDEX index_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_type, "KEY");
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "index_name");
ast = tryParserQuery(alter_p, "DROP PRIMARY KEY");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_type, "PRIMARY_KEY");
ast = tryParserQuery(alter_p, "DROP FOREIGN KEY fk_symbol");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "fk_symbol");
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_type, "FOREIGN");
ast = tryParserQuery(alter_p, "DROP column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "column_name");
ast = tryParserQuery(alter_p, "DROP COLUMN column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "column_name");
}
TEST(ParserAlterCommand, AlterAlterCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "ALTER CHECK constraint_name NOT ENFORCED");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_CHECK);
EXPECT_TRUE(ast->as<ASTAlterCommand>()->not_check_enforced);
EXPECT_EQ(ast->as<ASTAlterCommand>()->constraint_name, "constraint_name");
ast = tryParserQuery(alter_p, "ALTER CHECK constraint_name ENFORCED");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_CHECK);
EXPECT_FALSE(ast->as<ASTAlterCommand>()->not_check_enforced);
EXPECT_EQ(ast->as<ASTAlterCommand>()->constraint_name, "constraint_name");
ast = tryParserQuery(alter_p, "ALTER CONSTRAINT constraint_name NOT ENFORCED");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_CHECK);
EXPECT_TRUE(ast->as<ASTAlterCommand>()->not_check_enforced);
EXPECT_EQ(ast->as<ASTAlterCommand>()->constraint_name, "constraint_name");
ast = tryParserQuery(alter_p, "ALTER CONSTRAINT constraint_name ENFORCED");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_CHECK);
EXPECT_FALSE(ast->as<ASTAlterCommand>()->not_check_enforced);
EXPECT_EQ(ast->as<ASTAlterCommand>()->constraint_name, "constraint_name");
ast = tryParserQuery(alter_p, "ALTER INDEX index_name VISIBLE");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_INDEX_VISIBLE);
EXPECT_TRUE(ast->as<ASTAlterCommand>()->index_visible);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "index_name");
ast = tryParserQuery(alter_p, "ALTER INDEX index_name INVISIBLE");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_INDEX_VISIBLE);
EXPECT_FALSE(ast->as<ASTAlterCommand>()->index_visible);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "index_name");
ast = tryParserQuery(alter_p, "ALTER column_name SET DEFAULT other_column");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN_DEFAULT);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "column_name");
EXPECT_EQ(getIdentifierName(ast->as<ASTAlterCommand>()->default_expression), "other_column");
ast = tryParserQuery(alter_p, "ALTER column_name DROP DEFAULT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_COLUMN_DEFAULT);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "column_name");
ast = tryParserQuery(alter_p, "ALTER COLUMN column_name SET DEFAULT other_column");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN_DEFAULT);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "column_name");
EXPECT_EQ(getIdentifierName(ast->as<ASTAlterCommand>()->default_expression), "other_column");
ast = tryParserQuery(alter_p, "ALTER COLUMN column_name DROP DEFAULT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::DROP_COLUMN_DEFAULT);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "column_name");
}
TEST(ParserAlterCommand, RenameAlterCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "RENAME COLUMN old_column_name TO new_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::RENAME_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "new_column_name");
ast = tryParserQuery(alter_p, "RENAME KEY old_index_name TO new_index_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::RENAME_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_index_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "new_index_name");
ast = tryParserQuery(alter_p, "RENAME INDEX old_index_name TO new_index_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::RENAME_INDEX);
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_index_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "new_index_name");
ast = tryParserQuery(alter_p, "RENAME TO new_table_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::RENAME_FOREIGN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->index_name, "new_table_name");
}
TEST(ParserAlterCommand, ModifyAlterCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "MODIFY column_name INT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "");
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "");
EXPECT_FALSE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
ast = tryParserQuery(alter_p, "MODIFY column_name INT FIRST");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "");
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "");
EXPECT_TRUE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
ast = tryParserQuery(alter_p, "MODIFY column_name INT AFTER other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "");
EXPECT_FALSE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
ast = tryParserQuery(alter_p, "MODIFY COLUMN column_name INT AFTER other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "");
EXPECT_FALSE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "column_name");
}
TEST(ParserAlterCommand, ChangeAlterCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "CHANGE old_column_name new_column_name INT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_FALSE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "");
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "new_column_name");
ast = tryParserQuery(alter_p, "CHANGE old_column_name new_column_name INT FIRST");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_TRUE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "");
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "new_column_name");
ast = tryParserQuery(alter_p, "CHANGE old_column_name new_column_name INT AFTER other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_FALSE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "new_column_name");
ast = tryParserQuery(alter_p, "CHANGE COLUMN old_column_name new_column_name INT AFTER other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_COLUMN);
EXPECT_FALSE(ast->as<ASTAlterCommand>()->first);
EXPECT_EQ(ast->as<ASTAlterCommand>()->column_name, "other_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->old_name, "old_column_name");
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children.size(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->additional_columns->children[0]->as<ASTDeclareColumn>()->name, "new_column_name");
}
TEST(ParserAlterCommand, AlterOptionsCommand)
{
ParserAlterCommand alter_p;
ASTPtr ast = tryParserQuery(alter_p, "ALGORITHM DEFAULT");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_PROPERTIES);
EXPECT_EQ(ast->as<ASTAlterCommand>()->properties->as<ASTDeclareOptions>()->changes.size(), 1);
EXPECT_EQ(getIdentifierName(ast->as<ASTAlterCommand>()->properties->as<ASTDeclareOptions>()->changes["algorithm"]), "DEFAULT");
ast = tryParserQuery(alter_p, "AUTO_INCREMENT 1 CHECKSUM 1");
EXPECT_EQ(ast->as<ASTAlterCommand>()->type, ASTAlterCommand::MODIFY_PROPERTIES);
EXPECT_EQ(ast->as<ASTAlterCommand>()->properties->as<ASTDeclareOptions>()->changes.size(), 2);
EXPECT_EQ(ast->as<ASTAlterCommand>()->properties->as<ASTDeclareOptions>()->changes["checksum"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
EXPECT_EQ(ast->as<ASTAlterCommand>()->properties->as<ASTDeclareOptions>()->changes["auto_increment"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
EXPECT_THROW(tryParserQuery(alter_p, "ALGORITHM DEFAULT AUTO_INCREMENT 1"), Exception);
}