replica/table: adjust the view read-before-write to return static rows when needed

Adjusts the read-before-write query issued in
`table::do_push_view_replica_updates` so that, when needed, requests
static columns and makes sure that the static row is present.
This commit is contained in:
Piotr Dulikowski
2022-07-28 18:56:43 +02:00
parent 18be90b1e6
commit 6ab41d76e6
3 changed files with 24 additions and 6 deletions

View File

@@ -1510,6 +1510,12 @@ future<query::clustering_row_ranges> calculate_affected_clustering_ranges(const
}
bool needs_static_row(const mutation_partition& mp, const std::vector<view_and_base>& views) {
// TODO: We could also check whether any of the views need static rows
// and return false if none of them do
return mp.partition_tombstone() || !mp.static_row().empty();
}
// Calculate the node ("natural endpoint") to which this node should send
// a view update.
//

View File

@@ -305,6 +305,8 @@ future<query::clustering_row_ranges> calculate_affected_clustering_ranges(
const mutation_partition& mp,
const std::vector<view_and_base>& views);
bool needs_static_row(const mutation_partition& mp, const std::vector<view_and_base>& views);
struct wait_for_all_updates_tag {};
using wait_for_all_updates = bool_class<wait_for_all_updates_tag>;
future<> mutate_MV(

View File

@@ -2428,26 +2428,36 @@ future<row_locker::lock_holder> table::do_push_view_replica_updates(schema_ptr s
co_return row_locker::lock_holder();
}
auto cr_ranges = co_await db::view::calculate_affected_clustering_ranges(*base, m.decorated_key(), m.partition(), views);
if (cr_ranges.empty()) {
const bool need_regular = !cr_ranges.empty();
const bool need_static = db::view::needs_static_row(m.partition(), views);
if (!need_regular && !need_static) {
tracing::trace(tr_state, "View updates do not require read-before-write");
co_await generate_and_propagate_view_updates(base, sem.make_tracking_only_permit(s.get(), "push-view-updates-1", timeout), std::move(views), std::move(m), { }, std::move(tr_state), now);
// In this case we are not doing a read-before-write, just a
// write, so no lock is needed.
co_return row_locker::lock_holder();
}
// We read the whole set of regular columns in case the update now causes a base row to pass
// We read whole sets of regular and/or static columns in case the update now causes a base row to pass
// a view's filters, and a view happens to include columns that have no value in this update.
// Also, one of those columns can determine the lifetime of the base row, if it has a TTL.
auto columns = boost::copy_range<query::column_id_vector>(
base->regular_columns() | boost::adaptors::transformed(std::mem_fn(&column_definition::id)));
query::column_id_vector static_columns;
query::column_id_vector regular_columns;
if (need_regular) {
boost::copy(base->regular_columns() | boost::adaptors::transformed(std::mem_fn(&column_definition::id)), std::back_inserter(regular_columns));
}
if (need_static) {
boost::copy(base->static_columns() | boost::adaptors::transformed(std::mem_fn(&column_definition::id)), std::back_inserter(static_columns));
}
query::partition_slice::option_set opts;
opts.set(query::partition_slice::option::send_partition_key);
opts.set(query::partition_slice::option::send_clustering_key);
opts.set_if<query::partition_slice::option::send_clustering_key>(need_regular);
opts.set_if<query::partition_slice::option::distinct>(need_static && !need_regular);
opts.set_if<query::partition_slice::option::always_return_static_content>(need_static);
opts.set(query::partition_slice::option::send_timestamp);
opts.set(query::partition_slice::option::send_ttl);
opts.add(custom_opts);
auto slice = query::partition_slice(
std::move(cr_ranges), { }, std::move(columns), std::move(opts), { }, cql_serialization_format::internal(), query::max_rows);
std::move(cr_ranges), std::move(static_columns), std::move(regular_columns), std::move(opts), { }, cql_serialization_format::internal(), query::max_rows);
// Take the shard-local lock on the base-table row or partition as needed.
// We'll return this lock to the caller, which will release it after
// writing the base-table update.