diff --git a/src/Interpreters/InterpreterSystemQuery.cpp b/src/Interpreters/InterpreterSystemQuery.cpp index 18d31e2f89c..aac632bebc9 100644 --- a/src/Interpreters/InterpreterSystemQuery.cpp +++ b/src/Interpreters/InterpreterSystemQuery.cpp @@ -219,12 +219,12 @@ BlockIO InterpreterSystemQuery::execute() /// Make canonical query for simpler processing if (query.type == Type::RELOAD_DICTIONARY) { - if (!query.database.empty()) - query.table = query.database + "." + query.table; + if (!query.getDatabase().empty()) + query.setTable(query.getDatabase() + "." + query.getTable()); } - else if (!query.table.empty()) + else if (!query.getTable().empty()) { - table_id = getContext()->resolveStorageID(StorageID(query.database, query.table), Context::ResolveOrdinary); + table_id = getContext()->resolveStorageID(StorageID(query.getDatabase(), query.getTable()), Context::ResolveOrdinary); } @@ -296,7 +296,7 @@ BlockIO InterpreterSystemQuery::execute() getContext()->checkAccess(AccessType::SYSTEM_RELOAD_DICTIONARY); auto & external_dictionaries_loader = system_context->getExternalDictionariesLoader(); - external_dictionaries_loader.reloadDictionary(query.table, getContext()); + external_dictionaries_loader.reloadDictionary(query.getTable(), getContext()); ExternalDictionariesLoader::resetAll(); break; @@ -588,10 +588,10 @@ void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query) if (!dropReplicaImpl(query, table)) throw Exception(ErrorCodes::BAD_ARGUMENTS, table_is_not_replicated.data(), table_id.getNameForLogs()); } - else if (!query.database.empty()) + else if (!query.getDatabase().empty()) { - getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA, query.database); - DatabasePtr database = DatabaseCatalog::instance().getDatabase(query.database); + getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA, query.getDatabase()); + DatabasePtr database = DatabaseCatalog::instance().getDatabase(query.getDatabase()); for (auto iterator = database->getTablesIterator(getContext()); iterator->isValid(); iterator->next()) dropReplicaImpl(query, iterator->table()); LOG_TRACE(log, "Dropped replica {} from database {}", query.replica, backQuoteIfNeed(database->getDatabaseName())); @@ -782,84 +782,84 @@ AccessRightsElements InterpreterSystemQuery::getRequiredAccessForDDLOnCluster() case Type::STOP_MERGES: [[fallthrough]]; case Type::START_MERGES: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_MERGES); else - required_access.emplace_back(AccessType::SYSTEM_MERGES, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_MERGES, query.getDatabase(), query.getTable()); break; } case Type::STOP_TTL_MERGES: [[fallthrough]]; case Type::START_TTL_MERGES: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_TTL_MERGES); else - required_access.emplace_back(AccessType::SYSTEM_TTL_MERGES, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_TTL_MERGES, query.getDatabase(), query.getTable()); break; } case Type::STOP_MOVES: [[fallthrough]]; case Type::START_MOVES: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_MOVES); else - required_access.emplace_back(AccessType::SYSTEM_MOVES, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_MOVES, query.getDatabase(), query.getTable()); break; } case Type::STOP_FETCHES: [[fallthrough]]; case Type::START_FETCHES: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_FETCHES); else - required_access.emplace_back(AccessType::SYSTEM_FETCHES, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_FETCHES, query.getDatabase(), query.getTable()); break; } case Type::STOP_DISTRIBUTED_SENDS: [[fallthrough]]; case Type::START_DISTRIBUTED_SENDS: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_DISTRIBUTED_SENDS); else - required_access.emplace_back(AccessType::SYSTEM_DISTRIBUTED_SENDS, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_DISTRIBUTED_SENDS, query.getDatabase(), query.getTable()); break; } case Type::STOP_REPLICATED_SENDS: [[fallthrough]]; case Type::START_REPLICATED_SENDS: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_REPLICATED_SENDS); else - required_access.emplace_back(AccessType::SYSTEM_REPLICATED_SENDS, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_REPLICATED_SENDS, query.getDatabase(), query.getTable()); break; } case Type::STOP_REPLICATION_QUEUES: [[fallthrough]]; case Type::START_REPLICATION_QUEUES: { - if (query.table.empty()) + if (query.getTable().empty()) required_access.emplace_back(AccessType::SYSTEM_REPLICATION_QUEUES); else - required_access.emplace_back(AccessType::SYSTEM_REPLICATION_QUEUES, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_REPLICATION_QUEUES, query.getDatabase(), query.getTable()); break; } case Type::DROP_REPLICA: { - required_access.emplace_back(AccessType::SYSTEM_DROP_REPLICA, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_DROP_REPLICA, query.getDatabase(), query.getTable()); break; } case Type::RESTORE_REPLICA: { - required_access.emplace_back(AccessType::SYSTEM_RESTORE_REPLICA, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_RESTORE_REPLICA, query.getDatabase(), query.getTable()); break; } case Type::SYNC_REPLICA: { - required_access.emplace_back(AccessType::SYSTEM_SYNC_REPLICA, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_SYNC_REPLICA, query.getDatabase(), query.getTable()); break; } case Type::RESTART_REPLICA: { - required_access.emplace_back(AccessType::SYSTEM_RESTART_REPLICA, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_RESTART_REPLICA, query.getDatabase(), query.getTable()); break; } case Type::RESTART_REPLICAS: @@ -869,7 +869,7 @@ AccessRightsElements InterpreterSystemQuery::getRequiredAccessForDDLOnCluster() } case Type::FLUSH_DISTRIBUTED: { - required_access.emplace_back(AccessType::SYSTEM_FLUSH_DISTRIBUTED, query.database, query.table); + required_access.emplace_back(AccessType::SYSTEM_FLUSH_DISTRIBUTED, query.getDatabase(), query.getTable()); break; } case Type::FLUSH_LOGS: diff --git a/src/Parsers/ASTSystemQuery.cpp b/src/Parsers/ASTSystemQuery.cpp index ba8e49b98ca..b40078f3b67 100644 --- a/src/Parsers/ASTSystemQuery.cpp +++ b/src/Parsers/ASTSystemQuery.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -39,6 +40,36 @@ const char * ASTSystemQuery::typeToString(Type type) return type_name.data(); } +String ASTSystemQuery::getDatabase() const +{ + String name; + tryGetIdentifierNameInto(database, name); + return name; +} + +String ASTSystemQuery::getTable() const +{ + String name; + tryGetIdentifierNameInto(table, name); + return name; +} + +void ASTSystemQuery::setDatabase(const String & name) +{ + if (name.empty()) + database.reset(); + else + database = std::make_shared(name); +} + +void ASTSystemQuery::setTable(const String & name) +{ + if (name.empty()) + table.reset(); + else + table = std::make_shared(name); +} + void ASTSystemQuery::formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const { settings.ostr << (settings.hilite ? hilite_keyword : "") << "SYSTEM "; @@ -47,19 +78,19 @@ void ASTSystemQuery::formatImpl(const FormatSettings & settings, FormatState &, auto print_database_table = [&] { settings.ostr << " "; - if (!database.empty()) + if (!getDatabase().empty()) { - settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(database) + settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(getDatabase()) << (settings.hilite ? hilite_none : "") << "."; } - settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(table) + settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(getTable()) << (settings.hilite ? hilite_none : ""); }; auto print_drop_replica = [&] { settings.ostr << " " << quoteString(replica); - if (!table.empty()) + if (!getTable().empty()) { settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM TABLE" << (settings.hilite ? hilite_none : ""); @@ -70,11 +101,11 @@ void ASTSystemQuery::formatImpl(const FormatSettings & settings, FormatState &, settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM ZKPATH " << (settings.hilite ? hilite_none : "") << quoteString(replica_zk_path); } - else if (!database.empty()) + else if (!getDatabase().empty()) { settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM DATABASE " << (settings.hilite ? hilite_none : ""); - settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(database) + settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(getDatabase()) << (settings.hilite ? hilite_none : ""); } }; @@ -107,7 +138,7 @@ void ASTSystemQuery::formatImpl(const FormatSettings & settings, FormatState &, || type == Type::STOP_DISTRIBUTED_SENDS || type == Type::START_DISTRIBUTED_SENDS) { - if (!table.empty()) + if (!getTable().empty()) print_database_table(); else if (!volume.empty()) print_on_volume(); diff --git a/src/Parsers/ASTSystemQuery.h b/src/Parsers/ASTSystemQuery.h index 28d67a22578..12c1e260125 100644 --- a/src/Parsers/ASTSystemQuery.h +++ b/src/Parsers/ASTSystemQuery.h @@ -70,10 +70,17 @@ public: Type type = Type::UNKNOWN; + ASTPtr database; + ASTPtr table; + + String getDatabase() const; + String getTable() const; + + void setDatabase(const String & name); + void setTable(const String & name); + String target_model; String target_function; - String database; - String table; String replica; String replica_zk_path; bool is_drop_whole_replica{}; @@ -84,11 +91,20 @@ public: String getID(char) const override { return "SYSTEM query"; } - ASTPtr clone() const override { return std::make_shared(*this); } + ASTPtr clone() const override + { + auto res = std::make_shared(*this); + res->children.clear(); + + if (database) { res->database = database->clone(); res->children.push_back(res->database); } + if (table) { res->table = table->clone(); res->children.push_back(res->table); } + + return res; + } ASTPtr getRewrittenASTWithoutOnCluster(const std::string & new_database) const override { - return removeOnClusterSystem(clone(), new_database); + return removeOnCluster(clone(), new_database); } const char * getQueryKindString() const override { return "System"; } diff --git a/src/Parsers/ParserSystemQuery.cpp b/src/Parsers/ParserSystemQuery.cpp index b861cbd2a5a..4035200be38 100644 --- a/src/Parsers/ParserSystemQuery.cpp +++ b/src/Parsers/ParserSystemQuery.cpp @@ -39,14 +39,14 @@ static bool parseQueryWithOnClusterAndMaybeTable(std::shared_ptr ASTPtr ast; if (ParserStringLiteral{}.parse(pos, ast, expected)) { - res->database = {}; - res->table = ast->as().value.safeGet(); + res->setDatabase(""); + res->setTable(ast->as().value.safeGet()); parsed_table = true; } } if (!parsed_table) - parsed_table = parseDatabaseAndTableName(pos, expected, res->database, res->table); + parsed_table = parseDatabaseAndTableASTPtr(pos, expected, res->database, res->table); if (!parsed_table && require_table) return false; @@ -56,6 +56,12 @@ static bool parseQueryWithOnClusterAndMaybeTable(std::shared_ptr return false; res->cluster = cluster; + + if (res->database) + res->children.push_back(res->database); + if (res->table) + res->children.push_back(res->table); + return true; } @@ -163,14 +169,12 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & if (ParserKeyword{"DATABASE"}.ignore(pos, expected)) { ParserIdentifier database_parser; - ASTPtr database; - if (!database_parser.parse(pos, database, expected)) + if (!database_parser.parse(pos, res->database, expected)) return false; - tryGetIdentifierNameInto(database, res->database); } else if (ParserKeyword{"TABLE"}.ignore(pos, expected)) { - parseDatabaseAndTableName(pos, expected, res->database, res->table); + parseDatabaseAndTableASTPtr(pos, expected, res->database, res->table); } else if (ParserKeyword{"ZKPATH"}.ignore(pos, expected)) { @@ -193,7 +197,7 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & case Type::RESTART_REPLICA: case Type::SYNC_REPLICA: - if (!parseDatabaseAndTableName(pos, expected, res->database, res->table)) + if (!parseDatabaseAndTableASTPtr(pos, expected, res->database, res->table)) return false; break; @@ -251,7 +255,7 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & res->storage_policy = storage_policy_str; res->volume = volume_str; if (res->volume.empty() && res->storage_policy.empty()) - parseDatabaseAndTableName(pos, expected, res->database, res->table); + parseDatabaseAndTableASTPtr(pos, expected, res->database, res->table); break; } @@ -265,7 +269,7 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & case Type::START_REPLICATED_SENDS: case Type::STOP_REPLICATION_QUEUES: case Type::START_REPLICATION_QUEUES: - parseDatabaseAndTableName(pos, expected, res->database, res->table); + parseDatabaseAndTableASTPtr(pos, expected, res->database, res->table); break; case Type::SUSPEND: @@ -287,6 +291,11 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & break; } + if (res->database) + res->children.push_back(res->database); + if (res->table) + res->children.push_back(res->table); + node = std::move(res); return true; }