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:
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user