diff --git a/mutation_query.cc b/mutation_query.cc index 3ab0d2145a..ff6379d394 100644 --- a/mutation_query.cc +++ b/mutation_query.cc @@ -57,13 +57,14 @@ bool reconcilable_result::operator!=(const reconcilable_result& other) const { } query::result -to_data_query_result(const reconcilable_result& r, schema_ptr s, const query::partition_slice& slice, uint32_t max_partitions) { +to_data_query_result(const reconcilable_result& r, schema_ptr s, const query::partition_slice& slice, uint32_t max_rows, uint32_t max_partitions) { query::result::builder builder(slice, query::result_request::only_result, { }); for (const partition& p : r.partitions()) { - if (!max_partitions--) { + if (builder.row_count() >= max_rows || builder.partition_count() >= max_partitions) { break; } - p.mut().unfreeze(s).query(builder, slice, gc_clock::time_point::min(), query::max_rows); + // Also enforces the per-partition limit. + p.mut().unfreeze(s).query(builder, slice, gc_clock::time_point::min(), max_rows - builder.row_count()); } if (r.is_short_read()) { builder.mark_as_short_read(); diff --git a/mutation_query.hh b/mutation_query.hh index 35db45a53f..2009747d88 100644 --- a/mutation_query.hh +++ b/mutation_query.hh @@ -105,7 +105,7 @@ public: printer pretty_printer(schema_ptr) const; }; -query::result to_data_query_result(const reconcilable_result&, schema_ptr, const query::partition_slice&, uint32_t partition_limit = query::max_partitions); +query::result to_data_query_result(const reconcilable_result&, schema_ptr, const query::partition_slice&, uint32_t row_limit, uint32_t partition_limit); // Performs a query on given data source returning data in reconcilable form. // diff --git a/service/storage_proxy.cc b/service/storage_proxy.cc index 6c764c0a09..6c1d07c69e 100644 --- a/service/storage_proxy.cc +++ b/service/storage_proxy.cc @@ -2346,7 +2346,8 @@ protected: if (rr_opt && (can_send_short_read || data_resolver->all_reached_end() || rr_opt->row_count() >= original_row_limit() || data_resolver->live_partition_count() >= original_partition_limit()) && !data_resolver->any_partition_short_read()) { - auto result = ::make_foreign(::make_lw_shared(to_data_query_result(std::move(*rr_opt), _schema, _cmd->slice))); + auto result = ::make_foreign(::make_lw_shared( + to_data_query_result(std::move(*rr_opt), _schema, _cmd->slice, _cmd->row_limit, cmd->partition_limit))); // wait for write to complete before returning result to prevent multiple concurrent read requests to // trigger repair multiple times and to prevent quorum read to return an old value, even after a quorum // another read had returned a newer value (but the newer value had not yet been sent to the other replicas)