database: Fix view schemas in place when loading
On restart the view schemas are loaded and might contain old views with an unmarked computed column. We already have code to update the schema, but before we do it we load the view as is. This is not desired since once registered, this view version can be used for writes which is forbidden since we will spot a none computed column which is in the view's primary key but not in the base table at all. To solve this, in addition to altering the persistent schema, we fix the view's loaded schema in place. This is safe since computed column is just involved in generating a value for this column when creating a view update so the effect of this manipulation stays internal. The second stage of the in place fixing is to persist the changes made in the in place fixing so the view is ready for the next node restart in particular the `computed_columns` table.
This commit is contained in:
27
database.cc
27
database.cc
@@ -845,17 +845,22 @@ future<> database::parse_system_tables(distributed<service::storage_proxy>& prox
|
||||
});
|
||||
}).then([&proxy, &mm, this] {
|
||||
return do_parse_schema_tables(proxy, db::schema_tables::VIEWS, [this, &proxy, &mm] (schema_result_value_type &v) {
|
||||
return create_views_from_schema_partition(proxy, v.second).then([this, &mm] (std::vector<view_ptr> views) {
|
||||
return parallel_for_each(views.begin(), views.end(), [this, &mm] (auto&& v) {
|
||||
return this->add_column_family_and_make_directory(v).then([this, &mm, v] {
|
||||
// TODO: Remove once computed columns are guaranteed to be featured in the whole cluster.
|
||||
view_ptr fixed_v = maybe_fix_legacy_secondary_index_mv_schema(*this, v, nullptr, preserve_version::no);
|
||||
if (fixed_v) {
|
||||
return mm.local().announce_view_update(view_ptr(fixed_v));
|
||||
} else {
|
||||
return make_ready_future<>();
|
||||
}
|
||||
});
|
||||
return create_views_from_schema_partition(proxy, v.second).then([this, &mm, &proxy] (std::vector<view_ptr> views) {
|
||||
return parallel_for_each(views.begin(), views.end(), [this, &mm, &proxy] (auto&& v) {
|
||||
// TODO: Remove once computed columns are guaranteed to be featured in the whole cluster.
|
||||
// we fix here the schema in place in oreder to avoid races (write commands comming from other coordinators).
|
||||
view_ptr fixed_v = maybe_fix_legacy_secondary_index_mv_schema(*this, v, nullptr, preserve_version::yes);
|
||||
view_ptr v_to_add = fixed_v ? fixed_v : v;
|
||||
future<> f = this->add_column_family_and_make_directory(v_to_add);
|
||||
if (bool(fixed_v)) {
|
||||
v_to_add = fixed_v;
|
||||
auto&& keyspace = find_keyspace(v->ks_name()).metadata();
|
||||
auto mutations = db::schema_tables::make_update_view_mutations(keyspace, view_ptr(v), fixed_v, api::new_timestamp(), true);
|
||||
f = f.then([this, &proxy, mutations = std::move(mutations)] {
|
||||
return db::schema_tables::merge_schema(proxy, _feat, std::move(mutations));
|
||||
});
|
||||
}
|
||||
return f;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user