Before this commit, any attempt to create, alter, attach, or drop the default service level would result in a syntax error whose error message was unclear: ``` cqlsh> attach service level default to cassandra; SyntaxException: line 1:21 no viable alternative at input 'default' ``` The error stems from the grammar not being able to parse `default` as a correct service level name. To fix that, we cover it manually. This way, the grammar accepts it and we can process it in Scylla. The reason why we'd like to cover the default service level is that it's an actual service level that the user should reference. Getting a syntax error is not what should happen. Hence this fix. We validate the input and if the given role is really the default service level, we reject the query and provide an informative error message. Two validation tests are provided. Fixes scylladb/scylladb#26699 Closes scylladb/scylladb#27162
50 lines
1.9 KiB
C++
50 lines
1.9 KiB
C++
/*
|
|
* Copyright (C) 2021-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
*/
|
|
|
|
#include "seastarx.hh"
|
|
#include "cql3/statements/drop_service_level_statement.hh"
|
|
#include "service/qos/service_level_controller.hh"
|
|
#include "service/client_state.hh"
|
|
#include "service/query_state.hh"
|
|
|
|
namespace cql3 {
|
|
|
|
namespace statements {
|
|
|
|
drop_service_level_statement::drop_service_level_statement(sstring service_level, bool if_exists) :
|
|
_service_level(service_level), _if_exists(if_exists) {}
|
|
|
|
std::unique_ptr<cql3::statements::prepared_statement>
|
|
cql3::statements::drop_service_level_statement::prepare(
|
|
data_dictionary::database db, cql_stats &stats) {
|
|
return std::make_unique<prepared_statement>(audit_info(), ::make_shared<drop_service_level_statement>(*this));
|
|
}
|
|
|
|
future<> drop_service_level_statement::check_access(query_processor& qp, const service::client_state &state) const {
|
|
return state.ensure_has_permission(auth::command_desc{.permission = auth::permission::DROP, .resource = auth::root_service_level_resource()});
|
|
}
|
|
|
|
future<::shared_ptr<cql_transport::messages::result_message>>
|
|
drop_service_level_statement::execute(query_processor& qp,
|
|
service::query_state &state,
|
|
const query_options &,
|
|
std::optional<service::group0_guard> guard) const {
|
|
if (_service_level == qos::service_level_controller::default_service_level_name) {
|
|
sstring reason = seastar::format("The default service level, {}, cannot be dropped",
|
|
qos::service_level_controller::default_service_level_name);
|
|
throw exceptions::invalid_request_exception(std::move(reason));
|
|
}
|
|
service::group0_batch mc{std::move(guard)};
|
|
auto& sl = state.get_service_level_controller();
|
|
co_await sl.drop_distributed_service_level(_service_level, _if_exists, mc);
|
|
co_await sl.commit_mutations(std::move(mc));
|
|
co_return nullptr;
|
|
}
|
|
}
|
|
}
|