diff --git a/mutation_partition.cc b/mutation_partition.cc index c1f5369773..542d88f338 100644 --- a/mutation_partition.cc +++ b/mutation_partition.cc @@ -512,17 +512,13 @@ mutation_partition::clustered_row(const schema& s, const clustering_key_view& ke mutation_partition::rows_type::const_iterator mutation_partition::lower_bound(const schema& schema, const query::clustering_range& r) const { auto cmp = rows_entry::key_comparator(clustering_key_prefix::prefix_equality_less_compare(schema)); - return r.start() ? (r.start()->is_inclusive() - ? _rows.lower_bound(r.start()->value(), cmp) - : _rows.upper_bound(r.start()->value(), cmp)) : _rows.cbegin(); + return r.lower_bound(_rows, std::move(cmp)); } mutation_partition::rows_type::const_iterator mutation_partition::upper_bound(const schema& schema, const query::clustering_range& r) const { auto cmp = rows_entry::key_comparator(clustering_key_prefix::prefix_equality_less_compare(schema)); - return r.end() ? (r.end()->is_inclusive() - ? _rows.upper_bound(r.end()->value(), cmp) - : _rows.lower_bound(r.end()->value(), cmp)) : _rows.cend(); + return r.upper_bound(_rows, std::move(cmp)); } boost::iterator_range diff --git a/range.hh b/range.hh index 803dda77e9..5921778f58 100644 --- a/range.hh +++ b/range.hh @@ -592,6 +592,57 @@ public: deoverlapped_ranges.emplace_back(std::move(current)); return deoverlapped_ranges; } + +private: + // These private functions optimize the case where a sequence supports the + // lower and upper bound operations more efficiently, as is the case with + // some boost containers. + struct std_ {}; + struct built_in_ : std_ {}; + + template::type::lower_bound)> + typename std::remove_reference::type::const_iterator do_lower_bound(const T& value, Range&& r, LessComparator&& cmp, built_in_) const { + return r.lower_bound(value, std::forward(cmp)); + } + + template::type::upper_bound)> + typename std::remove_reference::type::const_iterator do_upper_bound(const T& value, Range&& r, LessComparator&& cmp, built_in_) const { + return r.upper_bound(value, std::forward(cmp)); + } + + template + typename std::remove_reference::type::const_iterator do_lower_bound(const T& value, Range&& r, LessComparator&& cmp, std_) const { + return std::lower_bound(r.begin(), r.end(), value, std::forward(cmp)); + } + + template + typename std::remove_reference::type::const_iterator do_upper_bound(const T& value, Range&& r, LessComparator&& cmp, std_) const { + return std::upper_bound(r.begin(), r.end(), value, std::forward(cmp)); + } +public: + // Return the lower bound of the specified sequence according to these bounds. + template + typename std::remove_reference::type::const_iterator lower_bound(Range&& r, LessComparator&& cmp) const { + return start() + ? (start()->is_inclusive() + ? do_lower_bound(start()->value(), std::forward(r), std::forward(cmp), built_in_()) + : do_upper_bound(start()->value(), std::forward(r), std::forward(cmp), built_in_())) + : std::cbegin(r); + } + // Return the upper bound of the specified sequence according to these bounds. + template + typename std::remove_reference::type::const_iterator upper_bound(Range&& r, LessComparator&& cmp) const { + return end() + ? (end()->is_inclusive() + ? do_upper_bound(end()->value(), std::forward(r), std::forward(cmp), built_in_()) + : do_lower_bound(end()->value(), std::forward(r), std::forward(cmp), built_in_())) + : (is_singular() + ? do_upper_bound(start()->value(), std::forward(r), std::forward(cmp), built_in_()) + : std::cend(r)); + } + template friend std::ostream& operator<<(std::ostream& out, const nonwrapping_range& r); };