From 3dda4d7dfb425d87245ca890d34cc7d60e8d2b8a Mon Sep 17 00:00:00 2001 From: zhang2014 Date: Fri, 10 Jul 2020 15:29:10 +0800 Subject: [PATCH] ISSUES-4006 add alter command parser --- src/Parsers/MySQL/ASTAlterCommand.cpp | 317 ++++++++++++++++++++++++++ src/Parsers/MySQL/ASTAlterCommand.h | 85 +++++++ src/Parsers/MySQL/ASTAlterQuery.cpp | 28 --- src/Parsers/MySQL/ASTAlterQuery.h | 34 --- 4 files changed, 402 insertions(+), 62 deletions(-) create mode 100644 src/Parsers/MySQL/ASTAlterCommand.cpp create mode 100644 src/Parsers/MySQL/ASTAlterCommand.h diff --git a/src/Parsers/MySQL/ASTAlterCommand.cpp b/src/Parsers/MySQL/ASTAlterCommand.cpp new file mode 100644 index 00000000000..7219b3de1d1 --- /dev/null +++ b/src/Parsers/MySQL/ASTAlterCommand.cpp @@ -0,0 +1,317 @@ +#include + +#include +#include +#include +#include +#include +#include + +namespace DB +{ + +namespace MySQLParser +{ + +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"); + + if (k_add.ignore(pos, expected)) + return parseAddCommand(pos, node, expected); + else if (k_drop.ignore(pos, expected)) + return parseDropCommand(pos, node, expected); + else if (k_alter.ignore(pos, expected)) + return parseAlterCommand(pos, node, expected); + else if (k_rename.ignore(pos, expected)) + return parseRenameCommand(pos, node, expected); + 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) +{ + ASTPtr declare_index; + ASTPtr additional_columns; + ParserDeclareIndex index_p; + ParserDeclareColumn column_p; + + auto alter_command = std::make_shared(); + + if (index_p.parse(pos, declare_index, expected)) + { + alter_command->type = ASTAlterCommand::ADD_INDEX; + alter_command->set(alter_command->index_decl, declare_index); + } + else + { + alter_command->type = ASTAlterCommand::ADD_COLUMN; + ParserKeyword("COLUMN").ignore(pos, expected); + + if (ParserToken(TokenType::OpeningRoundBracket).ignore(pos, expected)) + { + ParserList columns_p(std::make_unique(), std::make_unique(TokenType::Comma)); + + if (!columns_p.parse(pos, additional_columns, expected)) + return false; + + if (!ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected)) + return false; + } + else + { + ASTPtr declare_column; + if (!column_p.parse(pos, declare_column, expected)) + return false; + + additional_columns = std::make_shared(); + additional_columns->children.emplace_back(declare_column); + + 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); + } + } + + alter_command->set(alter_command->additional_columns, additional_columns); + } + + node = alter_command; + return true; +} + +bool ParserAlterCommand::parseDropCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected) +{ + ASTPtr name; + ParserIdentifier identifier_p; + + auto alter_command = std::make_shared(); + + if (ParserKeyword("PRIMARY KEY").ignore(pos, expected)) + { + alter_command->index_type = "PRIMARY_KEY"; + alter_command->type = ASTAlterCommand::DROP_INDEX; + } + else if (ParserKeyword("FOREIGN KEY").ignore(pos, expected)) + { + if (!identifier_p.parse(pos, name, expected)) + return false; + + alter_command->index_type = "FOREIGN"; + alter_command->type = ASTAlterCommand::DROP_INDEX; + alter_command->index_name = getIdentifierName(name); + } + else if (ParserKeyword("INDEX").ignore(pos, expected) || ParserKeyword("KEY").ignore(pos, expected)) + { + if (!identifier_p.parse(pos, name, expected)) + return false; + + alter_command->index_type = "KEY"; + alter_command->type = ASTAlterCommand::DROP_INDEX; + alter_command->index_name = getIdentifierName(name); + } + else if (ParserKeyword("CONSTRAINT").ignore(pos, expected) || ParserKeyword("CHECK").ignore(pos, expected)) + { + if (!identifier_p.parse(pos, name, expected)) + return false; + + alter_command->type = ASTAlterCommand::DROP_CHECK; + alter_command->constraint_name = getIdentifierName(name); + } + else + { + ParserKeyword("COLUMN").ignore(pos, expected); + + if (!identifier_p.parse(pos, name, expected)) + return false; + + alter_command->type = ASTAlterCommand::DROP_COLUMN; + alter_command->column_name = getIdentifierName(name); + } + + node = alter_command; + return true; +} + +bool ParserAlterCommand::parseAlterCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected) +{ + ASTPtr name; + + ParserIdentifier identifier_p; + auto alter_command = std::make_shared(); + + if (ParserKeyword("INDEX").ignore(pos, expected)) + { + /// ALTER INDEX index_name {VISIBLE | INVISIBLE} + + if (!identifier_p.parse(pos, name, expected)) + return false; + + alter_command->index_visible = ParserKeyword("VISIBLE").ignore(pos, expected); + + if (!alter_command->index_visible && !ParserKeyword("INVISIBLE").ignore(pos, expected)) + return false; + + alter_command->type = ASTAlterCommand::MODIFY_INDEX_VISIBLE; + alter_command->index_name = getIdentifierName(name); + } + else if (ParserKeyword("CHECK").ignore(pos, expected) || ParserKeyword("CONSTRAINT").ignore(pos, expected)) + { + /// ALTER {CHECK | CONSTRAINT} symbol [NOT] ENFORCED + if (!identifier_p.parse(pos, name, expected)) + return false; + + alter_command->not_check_enforced = ParserKeyword("NOT").ignore(pos, expected); + + if (!ParserKeyword("ENFORCED").ignore(pos, expected)) + return false; + + alter_command->type = ASTAlterCommand::MODIFY_CHECK; + alter_command->constraint_name = getIdentifierName(name); + } + else + { + /// ALTER [COLUMN] col_name {SET DEFAULT {literal | (expr)} | DROP DEFAULT} + + ParserKeyword("COLUMN").ignore(pos, expected); + + if (!identifier_p.parse(pos, name, expected)) + return false; + + if (ParserKeyword("DROP DEFAULT").ignore(pos, expected)) + alter_command->type = ASTAlterCommand::DROP_COLUMN_DEFAULT; + else if (ParserKeyword("SET DEFAULT").ignore(pos, expected)) + { + ASTPtr default_expression; + ParserExpression expression_p; + + if (!expression_p.parse(pos, default_expression, expected)) + return false; + + alter_command->type = ASTAlterCommand::MODIFY_COLUMN_DEFAULT; + alter_command->set(alter_command->default_expression, default_expression); + } + else + return false; + + alter_command->column_name = getIdentifierName(name); + } + + node = alter_command; + return true; +} + +bool ParserAlterCommand::parseRenameCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected) +{ + ASTPtr old_name; + ASTPtr new_name; + + ParserIdentifier identifier_p; + auto alter_command = std::make_shared(); + + if (ParserKeyword("COLUMN").ignore(pos, expected)) + { + if (!identifier_p.parse(pos, old_name, expected)) + return false; + + if (!ParserKeyword("TO").ignore(pos, expected)) + return false; + + if (!identifier_p.parse(pos, new_name, expected)) + return false; + + alter_command->type = ASTAlterCommand::RENAME_COLUMN; + alter_command->old_name = getIdentifierName(old_name); + alter_command->column_name = getIdentifierName(new_name); + } + else if (ParserKeyword("TO").ignore(pos, expected) || ParserKeyword("AS").ignore(pos, expected)) + { + if (!identifier_p.parse(pos, new_name, expected)) + return false; + + alter_command->type = ASTAlterCommand::RENAME_FOREIGN; + alter_command->index_name = getIdentifierName(new_name); + } + else if (ParserKeyword("INDEX").ignore(pos, expected) || ParserKeyword("KEY").ignore(pos, expected)) + { + if (!identifier_p.parse(pos, old_name, expected)) + return false; + + if (!ParserKeyword("TO").ignore(pos, expected)) + return false; + + if (!identifier_p.parse(pos, new_name, expected)) + return false; + + alter_command->type = ASTAlterCommand::RENAME_INDEX; + alter_command->old_name = getIdentifierName(old_name); + alter_command->index_name = getIdentifierName(new_name); + } + else + { + return false; + } + + node = alter_command; + return true; +} + +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] ... + + if (ParserKeyword("FORCE").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 + } + else + { + ASTPtr table_options; + ParserDeclareTableOptions table_options_p; + + if (!table_options_p.parse(pos, table_options, expected)) + return false; + + /// set. + } + + return false; +} + +} + +} diff --git a/src/Parsers/MySQL/ASTAlterCommand.h b/src/Parsers/MySQL/ASTAlterCommand.h new file mode 100644 index 00000000000..8cfe77ba81c --- /dev/null +++ b/src/Parsers/MySQL/ASTAlterCommand.h @@ -0,0 +1,85 @@ +#pragma once + +#include +#include +#include +#include + +namespace DB +{ + + +namespace MySQLParser +{ + +class ASTAlterCommand : public IAST +{ +public: + enum Type + { + ADD_INDEX, + ADD_COLUMN, + + DROP_INDEX, + DROP_CHECK, + DROP_COLUMN, + DROP_COLUMN_DEFAULT, + + RENAME_INDEX, + RENAME_COLUMN, + RENAME_FOREIGN, + + MODIFY_CHECK, + MODIFY_COLUMN, + MODIFY_TABLE_OPTIONS, + MODIFY_INDEX_VISIBLE, + MODIFY_COLUMN_DEFAULT, + + ORDER_BY, + + NO_TYPE + }; + + Type type = NO_TYPE; + + /// For ADD INDEX + ASTDeclareIndex * index_decl; + + /// For modify default expression + IAST * default_expression; + + /// For ADD COLUMN + ASTExpressionList * additional_columns; + + bool first = false; + bool index_visible = false; + bool not_check_enforced = false; + + String old_name; + String index_type; + String index_name; + String column_name; + String constraint_name; +}; + +class ParserAlterCommand : public IParserBase +{ +protected: + const char * getName() const override { return "alter command"; } + + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; + + bool parseAddCommand(Pos & pos, ASTPtr & node, Expected & expected); + + bool parseDropCommand(Pos & pos, ASTPtr & node, Expected & expected); + + bool parseAlterCommand(Pos & pos, ASTPtr & node, Expected & expected); + + bool parseRenameCommand(Pos & pos, ASTPtr & node, Expected & expected); + + bool parseOtherCommand(Pos & pos, ASTPtr & node, Expected & expected); +}; + +} + +} diff --git a/src/Parsers/MySQL/ASTAlterQuery.cpp b/src/Parsers/MySQL/ASTAlterQuery.cpp index 739f2da9f33..f97163130be 100644 --- a/src/Parsers/MySQL/ASTAlterQuery.cpp +++ b/src/Parsers/MySQL/ASTAlterQuery.cpp @@ -52,34 +52,6 @@ void ASTAlterQuery::formatImpl(const IAST::FormatSettings & settings, IAST::Form // static_cast(command_list)->formatImpl(settings, state, frame_nested); } -bool ParserAlterCommand::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected) -{ - ParserKeyword k_add("ADD"); - ParserKeyword k_drop("DROP"); - - if (k_add.ignore(pos, expected)) - return parseAddCommand(pos, node, expected); - else if (k_drop.ignore(pos, expected)) - return parseDropCommand(pos, node, expected); - return false; -} -bool ParserAlterCommand::parseAddCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected) -{ - ASTPtr declare_index; - ParserDeclareIndex p_index; - - /// TODO: add column - if (!p_index.parse(pos, declare_index, expected)) - return false; - - return true; -} -bool ParserAlterCommand::parseDropCommand(IParser::Pos & pos, ASTPtr & node, Expected & expected) -{ - - return false; -} - bool ParserAlterQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected) { ASTPtr table; diff --git a/src/Parsers/MySQL/ASTAlterQuery.h b/src/Parsers/MySQL/ASTAlterQuery.h index 3e8d8fd6c8c..a973be85b56 100644 --- a/src/Parsers/MySQL/ASTAlterQuery.h +++ b/src/Parsers/MySQL/ASTAlterQuery.h @@ -11,28 +11,6 @@ namespace DB namespace MySQLParser { -class ASTAlterCommand : public IAST -{ -public: - enum Type - { - ADD_COLUMN, - ADD_INDEX, - DROP_CONSTRAINT, - DROP_COLUMN, - DROP_INDEX, - DROP_PRIMARY_KEY, - DROP_FOREIGN_KEY, - }; - - /// For ADD INDEX - ASTDeclareIndex * add_index; - - /// For ADD COLUMN - ASTDeclareColumn * add_column; - -}; - class ASTAlterQuery : public IAST { public: @@ -48,18 +26,6 @@ protected: void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; }; -class ParserAlterCommand : public IParserBase -{ -protected: - const char * getName() const override { return "alter command"; } - - bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; - - bool parseAddCommand(Pos & pos, ASTPtr & node, Expected & expected); - - bool parseDropCommand(Pos & pos, ASTPtr & node, Expected & expected); -}; - class ParserAlterQuery : public IParserBase { protected: