cql3: enable non-frozen UDTs.

Add a cluster feature for non-frozen UDTs.

If the cluster supports non-frozen UDTs, do not return an error
message when trying to create a table with a non-frozen user type.
This commit is contained in:
Kamil Braun
2019-10-21 10:16:05 +02:00
parent 7ac7a3994d
commit e74b5deb5d
9 changed files with 29 additions and 15 deletions

View File

@@ -203,9 +203,9 @@ public:
_name.set_keyspace(keyspace);
}
try {
auto&& type = user_types.get_type(_name.get_user_type_name());
if (!is_frozen()) {
throw exceptions::invalid_request_exception("Non-frozen User-Defined types are not supported, please use frozen<>");
data_type type = user_types.get_type(_name.get_user_type_name());
if (is_frozen()) {
type = type->freeze();
}
return cql3_type(std::move(type));
} catch (std::out_of_range& e) {

View File

@@ -242,8 +242,8 @@ std::unique_ptr<prepared_statement> create_table_statement::raw_statement::prepa
throw exceptions::invalid_request_exception("Counter support is not enabled");
}
if (pt.get_type()->is_multi_cell()) {
// check for multi-cell types (non-frozen UDTs or collections) inside a non-frozen UDT
if (pt.get_type()->is_user_type()) {
// check for multi-cell types (non-frozen UDTs or collections) inside a non-frozen UDT
auto type = static_cast<const user_type_impl*>(pt.get_type().get());
for (auto&& inner: type->all_types()) {
if (inner->is_multi_cell()) {
@@ -252,6 +252,10 @@ std::unique_ptr<prepared_statement> create_table_statement::raw_statement::prepa
throw exceptions::invalid_request_exception("Non-frozen UDTs with nested non-frozen collections are not supported");
}
}
if (!service::get_local_storage_service().cluster_supports_nonfrozen_udts()) {
throw exceptions::invalid_request_exception("Non-frozen UDT support is not enabled");
}
}
if (!defined_multi_cell_columns) {

View File

@@ -133,8 +133,9 @@ inline user_type create_type_statement::create_type(database& db)
field_types.push_back(column_type->prepare(db, keyspace()).get_type());
}
// When a table is created with a UDT column, the column will be non-frozen (multi cell) by default.
return user_type_impl::get_instance(keyspace(), _name.get_user_type_name(),
std::move(field_names), std::move(field_types), false);
std::move(field_names), std::move(field_types), true /* multi cell */);
}
future<shared_ptr<cql_transport::event::schema_change>> create_type_statement::announce_migration(service::storage_proxy& proxy, bool is_local_only)

View File

@@ -116,7 +116,7 @@ public:
return to_bytes(s);
});
return user_type_impl::get_instance(keyspace, to_bytes(name), std::move(names), std::move(fields), false);
return user_type_impl::get_instance(keyspace, to_bytes(name), std::move(names), std::move(fields), true);
}
};

View File

@@ -235,7 +235,7 @@ data_type type_parser::get_abstract_type(const sstring& compare_with, type_parse
} else if (class_name == "org.apache.cassandra.db.marshal.UserType") {
auto [keyspace, name, field_names, field_types] = parser.get_user_type_parameters();
return user_type_impl::get_instance(
std::move(keyspace), std::move(name), std::move(field_names), std::move(field_types), false);
std::move(keyspace), std::move(name), std::move(field_names), std::move(field_types), multicell);
} else {
throw std::runtime_error("unknown type: " + class_name);
}

View File

@@ -112,6 +112,7 @@ static const sstring VIEW_VIRTUAL_COLUMNS = "VIEW_VIRTUAL_COLUMNS";
static const sstring DIGEST_INSENSITIVE_TO_EXPIRY = "DIGEST_INSENSITIVE_TO_EXPIRY";
static const sstring COMPUTED_COLUMNS_FEATURE = "COMPUTED_COLUMNS";
static const sstring CDC_FEATURE = "CDC";
static const sstring NONFROZEN_UDTS_FEATURE = "NONFROZEN_UDTS";
static const sstring SSTABLE_FORMAT_PARAM_NAME = "sstable_format";
@@ -171,6 +172,7 @@ storage_service::storage_service(abort_source& abort_source, distributed<databas
, _digest_insensitive_to_expiry(_feature_service, DIGEST_INSENSITIVE_TO_EXPIRY)
, _computed_columns(_feature_service, COMPUTED_COLUMNS_FEATURE)
, _cdc_feature(_feature_service, CDC_FEATURE)
, _nonfrozen_udts(_feature_service, NONFROZEN_UDTS_FEATURE)
, _la_feature_listener(*this, _feature_listeners_sem, sstables::sstable_version_types::la)
, _mc_feature_listener(*this, _feature_listeners_sem, sstables::sstable_version_types::mc)
, _replicate_action([this] { return do_replicate_to_all_cores(); })
@@ -228,7 +230,8 @@ void storage_service::enable_all_features() {
std::ref(_view_virtual_columns),
std::ref(_digest_insensitive_to_expiry),
std::ref(_computed_columns),
std::ref(_cdc_feature)
std::ref(_cdc_feature),
std::ref(_nonfrozen_udts)
})
{
if (features.count(f.name())) {
@@ -334,6 +337,7 @@ std::set<sstring> storage_service::get_config_supported_features_set() {
VIEW_VIRTUAL_COLUMNS,
DIGEST_INSENSITIVE_TO_EXPIRY,
COMPUTED_COLUMNS_FEATURE,
NONFROZEN_UDTS_FEATURE,
};
// Do not respect config in the case database is not started

View File

@@ -338,6 +338,7 @@ private:
gms::feature _digest_insensitive_to_expiry;
gms::feature _computed_columns;
gms::feature _cdc_feature;
gms::feature _nonfrozen_udts;
sstables::sstable_version_types _sstables_format = sstables::sstable_version_types::ka;
seastar::semaphore _feature_listeners_sem = {1};
@@ -2368,6 +2369,10 @@ public:
return bool(_computed_columns);
}
bool cluster_supports_nonfrozen_udts() const {
return bool(_nonfrozen_udts);
}
// Returns schema features which all nodes in the cluster advertise as supported.
db::schema_features cluster_schema_features() const;

View File

@@ -77,7 +77,7 @@ type_generator::type_generator(random_schema_specification& spec) : _spec(spec)
});
// user
_generators.emplace_back(
[this] (std::mt19937& engine, is_multi_cell) mutable {
[this] (std::mt19937& engine, is_multi_cell multi_cell) mutable {
std::uniform_int_distribution<size_t> count_dist{2, 4};
const auto count = count_dist(engine);
@@ -89,7 +89,7 @@ type_generator::type_generator(random_schema_specification& spec) : _spec(spec)
}
return user_type_impl::get_instance(_spec.keyspace_name(), to_bytes(_spec.udt_name(engine)), std::move(field_names),
std::move(field_types), false);
std::move(field_types), bool(multi_cell));
});
// list
_generators.emplace_back(

View File

@@ -183,14 +183,14 @@ SEASTAR_TEST_CASE(test_sort_type_in_update) {
service::migration_manager& mm = service::get_local_migration_manager();
auto&& keyspace = e.db().local().find_keyspace("ks").metadata();
auto type1 = user_type_impl::get_instance("ks", to_bytes("type1"), {}, {}, false);
auto type1 = user_type_impl::get_instance("ks", to_bytes("type1"), {}, {}, true);
auto muts1 = db::schema_tables::make_create_type_mutations(keyspace, type1, api::new_timestamp());
auto type3 = user_type_impl::get_instance("ks", to_bytes("type3"), {}, {}, false);
auto type3 = user_type_impl::get_instance("ks", to_bytes("type3"), {}, {}, true);
auto muts3 = db::schema_tables::make_create_type_mutations(keyspace, type3, api::new_timestamp());
// type2 must be created after type1 and type3. This tests that announce sorts them.
auto type2 = user_type_impl::get_instance("ks", to_bytes("type2"), {"field1", "field3"}, {type1, type3}, false);
auto type2 = user_type_impl::get_instance("ks", to_bytes("type2"), {"field1", "field3"}, {type1, type3}, true);
auto muts2 = db::schema_tables::make_create_type_mutations(keyspace, type2, api::new_timestamp());
auto muts = muts2;
@@ -450,10 +450,10 @@ SEASTAR_TEST_CASE(test_nested_type_mutation_in_update) {
service::migration_manager& mm = service::get_local_migration_manager();
auto&& keyspace = e.db().local().find_keyspace("ks").metadata();
auto type1 = user_type_impl::get_instance("ks", to_bytes("foo"), {"foo_k", "extra"}, {int32_type, int32_type}, false);
auto type1 = user_type_impl::get_instance("ks", to_bytes("foo"), {"foo_k", "extra"}, {int32_type, int32_type}, true);
auto muts1 = db::schema_tables::make_create_type_mutations(keyspace, type1, api::new_timestamp());
auto type2 = user_type_impl::get_instance("ks", to_bytes("bar"), {"bar_k", "extra"}, {type1, int32_type}, false);
auto type2 = user_type_impl::get_instance("ks", to_bytes("bar"), {"bar_k", "extra"}, {type1, int32_type}, true);
auto muts2 = db::schema_tables::make_create_type_mutations(keyspace, type2, api::new_timestamp());
auto muts = muts1;