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
57 lines
2.2 KiB
C++
57 lines
2.2 KiB
C++
/*
|
|
* Copyright (C) 2021-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
*/
|
|
|
|
#include "seastarx.hh"
|
|
#include "cql3/statements/alter_service_level_statement.hh"
|
|
#include "service/qos/service_level_controller.hh"
|
|
#include "service/raft/raft_group0_client.hh"
|
|
#include "service/client_state.hh"
|
|
#include "service/query_state.hh"
|
|
|
|
namespace cql3 {
|
|
|
|
namespace statements {
|
|
|
|
alter_service_level_statement::alter_service_level_statement(sstring service_level, shared_ptr<sl_prop_defs> attrs)
|
|
: _service_level(service_level) {
|
|
attrs->validate();
|
|
_slo = attrs->get_service_level_options();
|
|
}
|
|
|
|
std::unique_ptr<cql3::statements::prepared_statement>
|
|
cql3::statements::alter_service_level_statement::prepare(
|
|
data_dictionary::database db, cql_stats &stats) {
|
|
return std::make_unique<prepared_statement>(audit_info(), ::make_shared<alter_service_level_statement>(*this));
|
|
}
|
|
|
|
future<> alter_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::ALTER, .resource = auth::root_service_level_resource()});
|
|
}
|
|
|
|
future<::shared_ptr<cql_transport::messages::result_message>>
|
|
alter_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 altered",
|
|
qos::service_level_controller::default_service_level_name);
|
|
throw exceptions::invalid_request_exception(std::move(reason));
|
|
}
|
|
|
|
service::group0_batch mc{std::move(guard)};
|
|
validate_shares_option(qp, _slo);
|
|
qos::service_level& sl = state.get_service_level_controller().get_service_level(_service_level);
|
|
qos::service_level_options slo = _slo.replace_defaults(sl.slo);
|
|
auto& slc = state.get_service_level_controller();
|
|
co_await slc.alter_distributed_service_level(_service_level, slo, mc);
|
|
co_await slc.commit_mutations(std::move(mc));
|
|
co_return nullptr;
|
|
}
|
|
}
|
|
}
|