diff --git a/cql3/selection/selection.cc b/cql3/selection/selection.cc index 8c02f47406..73fa9293fa 100644 --- a/cql3/selection/selection.cc +++ b/cql3/selection/selection.cc @@ -263,9 +263,11 @@ selection::collect_metadata(schema_ptr schema, const std::vector<::shared_ptr group_by_cell_indices) : _result_set(std::make_unique(::make_shared(*(s.get_result_metadata())))) , _selectors(s.new_selectors()) + , _group_by_cell_indices(std::move(group_by_cell_indices)) , _now(now) , _cql_serialization_format(sf) { diff --git a/cql3/selection/selection.hh b/cql3/selection/selection.hh index 3cc5c9cffb..458c9aaa65 100644 --- a/cql3/selection/selection.hh +++ b/cql3/selection/selection.hh @@ -244,6 +244,7 @@ class result_set_builder { private: std::unique_ptr _result_set; std::unique_ptr _selectors; + const std::vector _group_by_cell_indices; ///< Indices in \c current of cells holding GROUP BY values. public: std::optional> current; private: @@ -306,7 +307,8 @@ public: bool do_filter(const selection& selection, const std::vector& pk, const std::vector& ck, const query::result_row_view& static_row, const query::result_row_view& row) const; }; - result_set_builder(const selection& s, gc_clock::time_point now, cql_serialization_format sf); + result_set_builder(const selection& s, gc_clock::time_point now, cql_serialization_format sf, + std::vector group_by_cell_indices = {}); void add_empty(); void add(bytes_opt value); void add(const column_definition& def, const query::result_atomic_cell_view& c); diff --git a/cql3/statements/select_statement.cc b/cql3/statements/select_statement.cc index edd6b0d20b..ef8baa8cab 100644 --- a/cql3/statements/select_statement.cc +++ b/cql3/statements/select_statement.cc @@ -317,7 +317,8 @@ select_statement::do_execute(service::storage_proxy& proxy, // An aggregation query will never be paged for the user, but we always page it internally to avoid OOM. // If we user provided a page_size we'll use that to page internally (because why not), otherwise we use our default // Note that if there are some nodes in the cluster with a version less than 2.0, we can't use paging (CASSANDRA-6707). - const bool aggregate = _selection->is_aggregate(); + // Also note: all GROUP BY queries are considered aggregation. + const bool aggregate = _selection->is_aggregate() || has_group_by(); const bool nonpaged_filtering = restrictions_need_filtering && page_size <= 0; if (aggregate || nonpaged_filtering) { page_size = DEFAULT_COUNT_PAGE_SIZE; @@ -339,7 +340,7 @@ select_statement::do_execute(service::storage_proxy& proxy, if (aggregate || nonpaged_filtering) { return do_with( cql3::selection::result_set_builder(*_selection, now, - options.get_cql_serialization_format()), + options.get_cql_serialization_format(), *_group_by_cell_indices), [this, p, page_size, now, timeout_duration, restrictions_need_filtering](auto& builder) { return do_until([p] {return p->is_exhausted();}, [p, &builder, page_size, now, timeout_duration] { diff --git a/cql3/statements/select_statement.hh b/cql3/statements/select_statement.hh index 5516f621d1..5f4dab64c0 100644 --- a/cql3/statements/select_statement.hh +++ b/cql3/statements/select_statement.hh @@ -142,6 +142,8 @@ public: ::shared_ptr get_restrictions() const; + bool has_group_by() { return _group_by_cell_indices && !_group_by_cell_indices->empty(); } + protected: uint32_t do_get_limit(const query_options& options, ::shared_ptr limit) const; uint32_t get_limit(const query_options& options) const {