Merge 'Fix parsing of initial tablets by ALTER' from Pavel Emelyanov

If the user wants to change the default initial tablets value, it uses ALTER KEYSPACE statement. However, specifying `WITH tablets = { initial: $value }`  will take no effect, because statement analyzer only applies `tablets` parameters together with the `replication` ones, so the working statement should be `WITH replication = $old_parameters AND tablets = ...` which is not very convenient.

This PR changes the analyzer so that altering `tablets` happens independently from `replication`. Test included.

fixes: #18801

Closes scylladb/scylladb#18899

* github.com:scylladb/scylladb:
  cql-pytest: Add validation of ALTER KEYSPACE WITH TABLETS
  cql3: Fix parsing of ALTER KEYSPACE's tablets parameters
  cql3: Remove unused ks_prop_defs/prepare_options() argument
This commit is contained in:
Nadav Har'El
2024-05-27 23:10:38 +03:00
2 changed files with 19 additions and 5 deletions

View File

@@ -24,7 +24,6 @@ static std::map<sstring, sstring> prepare_options(
const sstring& strategy_class,
const locator::token_metadata& tm,
std::map<sstring, sstring> options,
std::optional<unsigned>& initial_tablets,
const std::map<sstring, sstring>& old_options = {}) {
options.erase(ks_prop_defs::REPLICATION_STRATEGY_CLASS_KEY);
@@ -162,7 +161,7 @@ std::optional<sstring> ks_prop_defs::get_replication_strategy_class() const {
lw_shared_ptr<data_dictionary::keyspace_metadata> ks_prop_defs::as_ks_metadata(sstring ks_name, const locator::token_metadata& tm, const gms::feature_service& feat) {
auto sc = get_replication_strategy_class().value();
std::optional<unsigned> initial_tablets = get_initial_tablets(sc, feat.tablets);
auto options = prepare_options(sc, tm, get_replication_options(), initial_tablets);
auto options = prepare_options(sc, tm, get_replication_options());
return data_dictionary::keyspace_metadata::new_keyspace(ks_name, sc,
std::move(options), initial_tablets, get_boolean(KW_DURABLE_WRITES, true), get_storage_options());
}
@@ -171,13 +170,14 @@ lw_shared_ptr<data_dictionary::keyspace_metadata> ks_prop_defs::as_ks_metadata_u
std::map<sstring, sstring> options;
const auto& old_options = old->strategy_options();
auto sc = get_replication_strategy_class();
std::optional<unsigned> initial_tablets;
if (sc) {
initial_tablets = get_initial_tablets(*sc, old->initial_tablets().has_value());
options = prepare_options(*sc, tm, get_replication_options(), initial_tablets, old_options);
options = prepare_options(*sc, tm, get_replication_options(), old_options);
} else {
sc = old->strategy_name();
options = old_options;
}
std::optional<unsigned> initial_tablets = get_initial_tablets(*sc, old->initial_tablets().has_value());
if (!initial_tablets) {
initial_tablets = old->initial_tablets();
}

View File

@@ -100,6 +100,20 @@ def test_alter_changes_initial_tablets(cql, skip_without_tablets):
assert res.initial_tablets == 2
def test_alter_changes_initial_tablets_short(cql, skip_without_tablets):
ksdef = "WITH replication = {'class': 'NetworkTopologyStrategy', 'replication_factor': 1} AND tablets = {'initial': 1};"
with new_test_keyspace(cql, ksdef) as keyspace:
orig_rep = cql.execute(f"SELECT replication FROM system_schema.keyspaces WHERE keyspace_name = '{keyspace}'").one()
cql.execute(f"ALTER KEYSPACE {keyspace} WITH tablets = {{'initial': 2}};")
res = cql.execute(f"SELECT * FROM system_schema.scylla_keyspaces WHERE keyspace_name = '{keyspace}'").one()
assert res.initial_tablets == 2
# Test that replication parameters didn't change
rep = cql.execute(f"SELECT replication FROM system_schema.keyspaces WHERE keyspace_name = '{keyspace}'").one()
assert rep.replication == orig_rep.replication
# Test that initial number of tablets is preserved in describe
def test_describe_initial_tablets(cql, skip_without_tablets):
ksdef = "WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'replication_factor' : '1' } " \