MySQL 9.6.0
Source Code Documentation
nested_set_intersection_iterator.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_SETS_NESTED_SET_INTERSECTION_ITERATOR_H
25#define MYSQL_SETS_NESTED_SET_INTERSECTION_ITERATOR_H
26
27/// @file
28/// Experimental API header
29
30#include "mysql/sets/binary_operation.h" // Binary_operation
31#include "mysql/sets/nested_set_binary_operation_iterator_base.h" // Nested_set_binary_operation_iterator_base
32#include "mysql/sets/nested_set_meta.h" // Is_nested_set
33#include "mysql/sets/set_categories_and_traits.h" // Is_compatible_set
34
35/// @addtogroup GroupLibsMysqlSets
36/// @{
37
38namespace mysql::sets::detail {
39
40/// Iterator over the intersection of two sets.
41///
42/// @tparam Source1_tp The first source.
43///
44/// @tparam Source2_tp The second source.
45template <Is_nested_set Source1_tp, Is_nested_set Source2_tp>
46 requires Is_compatible_set<Source1_tp, Source2_tp>
49 Nested_set_intersection_iterator<Source1_tp, Source2_tp>, Source1_tp,
50 Source2_tp, Binary_operation::op_intersection> {
53 Self_t, Source1_tp, Source2_tp, Binary_operation::op_intersection>;
54
55 public:
56 // This iterator holds iterators into each source. Each source iterator has to
57 // skip keys that don't exist in the other set, and keys for which the
58 // intersections of mapped sets is empty. Therefore, advancing the iterator
59 // has two phases:
60 //
61 // 1. Advance both source iterators one step.
62 //
63 // 2. While the iterators point to different keys, or the mapped sets
64 // intersect, step the iterators forward (according the scheme in
65 // advance_if_needed).
66 //
67 // This iterator performs only phase 1 at the time the increment is requested,
68 // and performs phase 2 "lazily", i.e., only when it is needed, which is at
69 // the next dereference, advancement, or comparison operation.
70
71 using typename Base_t::Iterator1_t;
72 using typename Base_t::Iterator2_t;
73 using typename Base_t::Key_traits_t;
74 using typename Base_t::Source1_t;
75 using typename Base_t::Source2_t;
76 using typename Base_t::Value_t;
77
79
80 // Construct from two sources and one iterator into each of them.
82 const Source2_t *source2,
85 : Base_t(source1, source2, iterator1, iterator2) {}
86
87 /// @return The value that this iterator currently points to.
88 [[nodiscard]] auto get() const {
89 clean();
90 return this->make_value();
91 }
92
93 /// Move to the next iterator position.
94 void next() {
95 clean();
96 ++this->m_iterator1;
97 ++this->m_iterator2;
98 m_is_dirty = true;
99 }
100
101 /// @return true if this iterator equals other.
102 [[nodiscard]] bool is_equal(
103 const Nested_set_intersection_iterator &other) const {
104 clean();
105 return this->m_iterator1 == other.m_iterator1;
106 }
107
108 private:
109 /// True when the first phase of advancing the position but not the second one
110 /// has completed.
111 mutable bool m_is_dirty{true};
112
113 /// Perform the second phase of advancing the position, unless it has already
114 /// been done.
115 void clean() const {
116 if (m_is_dirty) {
118 m_is_dirty = false;
119 }
120 }
121
122 /// Whether the iteration is done or not.
123 // NOLINTNEXTLINE(performance-enum-size): silence clang-tidy's pointless hint
124 enum class Done { no, yes };
125
126 /// Perform the second phase of advancing the position.
127 void advance_if_needed() const {
128 auto &source1 = this->m_source1;
129 auto &source2 = this->m_source2;
130 auto &it1 = this->m_iterator1;
131 auto &it2 = this->m_iterator2;
132
133 // While both iterators point to the same key, increment both iterators
134 // using ++.
135 while (true) {
136 if (it1 == source1.end()) {
137 it2 = source2.end();
138 return;
139 }
140 if (it2 == source2.end()) {
141 it1 = source1.end();
142 return;
143 }
144 auto order = Key_traits_t::cmp(it1->first, it2->first);
145 if (order != 0) {
146 // The iterators point to different keys, so the loop condition no
147 // longer holds. So we break this loop. Before we break this loop, make
148 // sure that the loop condition for the second loop holds.
149 if (order > 0) {
150 if (step_and_check_done(source2, source1, it2, it1) == Done::yes)
151 return;
152 }
153 break;
154 }
155 if (is_intersecting(it1->second, it2->second)) return;
156 ++it1;
157 ++it2;
158 }
159
160 // While one iterator is less than the other, increment the smaller one
161 // by using it as the cursor for find().
162 while (true) {
163 // Invariant: *it1 < *it2 && it2 != end
164 if (step_and_check_done(source1, source2, it1, it2) == Done::yes) return;
165 // Invariant: *it2 < *it1 && it1 != end
166 if (step_and_check_done(source2, source1, it2, it1) == Done::yes) return;
167 }
168 }
169
170 /// Assuming none of it and other_it is at the end, and *it < *other_it,
171 /// advance it to point to an element with the same key as other_it if one
172 /// exists and the mapped sets intersect; otherwise advance it to the next
173 /// element if that is not end; otherwise set both iterators to the end.
174 ///
175 /// @param source The source that `it` points into.
176 ///
177 /// @param other_source The source that `other_it` points into.
178 ///
179 /// @param it The smaller of the iterators, which we will step.
180 ///
181 /// @param other_it The greater of the iterators.
182 ///
183 /// @retval Done::yes Iteration is done, because either `it` and `other_it`
184 /// point to the same key and the mapped sets intersect, or `it` reached the
185 /// end.
186 ///
187 /// @retval Done::no Iteration is not done, because `it` does not have a key
188 /// equal to the one that `other_it` points to. In this case, `it` has
189 /// advanced to the next element, and that is not the end iterator.
190 Done step_and_check_done(const auto &source, const auto &other_source,
191 auto &it, auto &other_it) const {
192 auto pos = source->find(it, other_it->first);
193 if (pos != source->end()) {
194 // Found `pos` in `source`, which has the same key as `other_it`.
195 if (is_intersecting(other_it->second, pos->second)) {
196 // The mapped sets intersect, so (pos, other_it) is a valid position.
197 it = pos;
198 return Done::yes;
199 }
200 }
201 if (it == source->end()) {
202 // Reached end of source without finding any pair of keys for which the
203 // mapped sets intersect.
204 other_it = other_source->end();
205 return Done::yes;
206 }
207 return Done::no;
208 }
209}; // class Nested_set_intersection_iterator
210
211} // namespace mysql::sets::detail
212
213// addtogroup GroupLibsMysqlSets
214/// @}
215
216#endif // ifndef MYSQL_SETS_NESTED_SET_INTERSECTION_ITERATOR_H
Experimental API header.
Self_tp Self_t
Definition: iterator_interface.h:372
Common base class for the forward iterators over union view, intersection view, and subtraction view ...
Definition: nested_set_binary_operation_iterator_base.h:54
Source2_tp Source2_t
Definition: nested_set_binary_operation_iterator_base.h:57
typename Source2_t::Const_iterator_t Iterator2_t
Definition: nested_set_binary_operation_iterator_base.h:63
typename Source1_tp::Key_traits_t Key_traits_t
Definition: nested_set_binary_operation_iterator_base.h:64
std::pair< const Key_t, Mapped_t > Value_t
Definition: nested_set_binary_operation_iterator_base.h:69
Source1_tp Source1_t
Definition: nested_set_binary_operation_iterator_base.h:56
const auto & iterator2() const
Return const reference to the current iterator into the second set.
Definition: nested_set_binary_operation_iterator_base.h:106
typename Source1_t::Const_iterator_t Iterator1_t
Definition: nested_set_binary_operation_iterator_base.h:62
Value_t make_value() const
Return the current value, computed as operation(m_iterator1, m_iterator2).
Definition: nested_set_binary_operation_iterator_base.h:113
const auto & iterator1() const
Return const reference to the current iterator into the first set.
Definition: nested_set_binary_operation_iterator_base.h:100
Iterator over the intersection of two sets.
Definition: nested_set_intersection_iterator.h:50
Source2_tp Source2_t
Definition: nested_set_binary_operation_iterator_base.h:57
bool is_equal(const Nested_set_intersection_iterator &other) const
Definition: nested_set_intersection_iterator.h:102
Nested_set_intersection_iterator(const Source1_t *source1, const Source2_t *source2, const Iterator1_t &iterator1, const Iterator2_t &iterator2)
Definition: nested_set_intersection_iterator.h:81
void next()
Move to the next iterator position.
Definition: nested_set_intersection_iterator.h:94
typename Source2_t::Const_iterator_t Iterator2_t
Definition: nested_set_binary_operation_iterator_base.h:63
void clean() const
Perform the second phase of advancing the position, unless it has already been done.
Definition: nested_set_intersection_iterator.h:115
Nested_set_intersection_iterator< Source1_tp, Source2_tp > Self_t
Definition: nested_set_intersection_iterator.h:51
auto get() const
Definition: nested_set_intersection_iterator.h:88
bool m_is_dirty
True when the first phase of advancing the position but not the second one has completed.
Definition: nested_set_intersection_iterator.h:111
Source1_tp Source1_t
Definition: nested_set_binary_operation_iterator_base.h:56
void advance_if_needed() const
Perform the second phase of advancing the position.
Definition: nested_set_intersection_iterator.h:127
Done step_and_check_done(const auto &source, const auto &other_source, auto &it, auto &other_it) const
Assuming none of it and other_it is at the end, and *it < *other_it, advance it to point to an elemen...
Definition: nested_set_intersection_iterator.h:190
typename Source1_t::Const_iterator_t Iterator1_t
Definition: nested_set_binary_operation_iterator_base.h:62
Done
Whether the iteration is done or not.
Definition: nested_set_intersection_iterator.h:124
static int cmp(Bigint *a, Bigint *b)
Definition: dtoa.cc:1064
Definition: aliases.h:97
constexpr bool is_intersecting(const Interval< Set_traits_t > &interval, const Is_boundary_set_over_traits< Set_traits_t > auto &set)
Return true if the left Interval and the right Boundary set intersect (overlap).
Definition: boundary_set_predicates.h:121
Experimental API header.
repeated Source source
Definition: replication_asynchronous_connection_failover.proto:42
Experimental API header.