diff --git a/cql3/statements/sl_prop_defs.cc b/cql3/statements/sl_prop_defs.cc index 6e86418582..70a5d3fd5e 100644 --- a/cql3/statements/sl_prop_defs.cc +++ b/cql3/statements/sl_prop_defs.cc @@ -38,6 +38,12 @@ void sl_prop_defs::validate() { } data_value v = duration_type->deserialize(duration_type->from_string(*repr)); cql_duration duration = static_pointer_cast(duration_type)->from_value(v); + if (duration.months || duration.days) { + throw exceptions::invalid_request_exception("Timeout values cannot be longer than 24h"); + } + if (duration.nanoseconds % 1'000'000 != 0) { + throw exceptions::invalid_request_exception("Timeout values must be expressed in millisecond granularity"); + } return std::chrono::duration_cast(std::chrono::nanoseconds(duration.nanoseconds)); }; diff --git a/db/system_distributed_keyspace.cc b/db/system_distributed_keyspace.cc index 250376be39..b3df493ded 100644 --- a/db/system_distributed_keyspace.cc +++ b/db/system_distributed_keyspace.cc @@ -598,10 +598,20 @@ future system_distributed_keyspace::get_service_level( future<> system_distributed_keyspace::set_service_level(sstring service_level_name, qos::service_level_options slo) const { static sstring prepared_query = format("INSERT INTO {}.{} (service_level) VALUES (?);", NAME, SERVICE_LEVELS); co_await _qp.execute_internal(prepared_query, db::consistency_level::ONE, internal_distributed_query_state(), {service_level_name}); - auto to_data_value = [&] (const std::optional& d) { - return d - ? data_value(cql_duration(months_counter{0}, days_counter{0}, nanoseconds_counter{std::chrono::duration_cast(*d).count()})) - : data_value::make_null(duration_type); + auto to_data_value = [&] (const qos::service_level_options::timeout_type& tv) { + return std::visit(overloaded_functor { + [&] (const qos::service_level_options::unset_marker&) { + return data_value::make_null(duration_type); + }, + [&] (const qos::service_level_options::delete_marker&) { + return data_value::make_null(duration_type); + }, + [&] (const lowres_clock::duration& d) { + return data_value(cql_duration(months_counter{0}, + days_counter{0}, + nanoseconds_counter{std::chrono::duration_cast(d).count()})); + }, + }, tv); }; co_await _qp.execute_internal(format("UPDATE {}.{} SET timeout = ? WHERE service_level = ?;", NAME, SERVICE_LEVELS), db::consistency_level::ONE,