mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
Condition.hpp
Go to the documentation of this file.
1#pragma once
2
3
5#include <stdexcept>
6#include <typeindex>
7#include <unordered_map>
8
9
10namespace m {
11
12
13/*======================================================================================================================
14 * helper structure
15 *====================================================================================================================*/
16
17template<typename Property, bool Ordered>
19{
20 private:
22 {
23 std::size_t operator()(const Schema::Identifier &id) const {
24 return id.prefix.has_value()
25 ? murmur3_64(intptr_t(*id.prefix) ^ intptr_t(*id.name))
26 : murmur3_64(intptr_t(*id.name));
27 }
28 };
29
30 using map_t = std::conditional_t<Ordered, std::vector<std::pair<Schema::Identifier, Property>>,
31 std::unordered_map<Schema::Identifier, Property, IdentifierHash>>;
32
34
35 public:
36 void add(Schema::Identifier id, Property P) {
37 auto it = find(id);
38 if (it == cend()) {
39 if constexpr (Ordered)
40 attrs.emplace_back(std::move(id), std::move(P));
41 else
42 attrs.emplace_hint(it, std::move(id), std::move(P));
43 } else {
44 throw invalid_argument("identifier already in use");
45 }
46 }
47
49 if constexpr (Ordered) {
50 auto pred = [this](const auto &p) -> bool { return this->find(p.first) == this->cend(); };
51 if (not std::all_of(other.cbegin(), other.cend(), pred))
52 throw invalid_argument("identifier already in use");
53 this->attrs.insert(this->cend(), other.begin(), other.end());
54 } else {
55 this->attrs.merge(other.attrs);
56 if (not other.attrs.empty())
57 throw invalid_argument("identifier already in use");
58 }
59 }
60
61 auto find(const Schema::Identifier &id) const {
62 if constexpr (Ordered) {
63 auto pred = [&id](const auto &e) -> bool { return e.first == id; };
64 auto it = std::find_if(cbegin(), cend(), pred);
65 if (it != cend() and std::find_if(std::next(it), cend(), pred) != cend())
66 throw invalid_argument("duplicate identifier, lookup ambiguous");
67 return it;
68 } else {
69 return attrs.find(id);
70 }
71 }
72
73 void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>> &old2new) {
74 auto old = std::exchange(*this, ConditionPropertyMap());
75 for (auto &[old_id, new_id] : old2new) {
76 /*----- Try to find the entry with the old ID. -----*/
77 auto it = old.find(old_id);
78 if (it != old.cend()) {
79 /*----- Insert found entry again with the new ID. -----*/
80 this->add(new_id, std::move(it->second));
81 }
82 }
83 }
84
85 auto begin() { return attrs.begin(); }
86 auto end() { return attrs.end(); }
87 auto begin() const { return attrs.cbegin(); }
88 auto end() const { return attrs.cend(); }
89 auto cbegin() const { return begin(); }
90 auto cend() const { return end(); }
91
92 bool empty() const { return attrs.empty(); }
93
94 bool operator==(const ConditionPropertyMap &other) const { return this->attrs == other.attrs; }
95};
96
97template<typename Property>
99template<typename Property>
101
102
103/*======================================================================================================================
104 * Condition
105 *====================================================================================================================*/
106
108{
109 friend struct ConditionSet;
110
111 virtual ~Condition() { };
112
113 private:
115 virtual std::unique_ptr<Condition> clone() const = 0;
116
117 public:
119 virtual bool implied_by(const Condition &other) const = 0;
120
124 virtual void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>> &old2new) = 0;
125
126 virtual bool operator==(const Condition &other) const = 0;
127 bool operator!=(const Condition &other) const { return not operator==(other); }
128};
129
131{
132 explicit Unsatisfiable() = default;
133 explicit Unsatisfiable(const Unsatisfiable&) = default;
135
136 private:
137 std::unique_ptr<Condition> clone() const override { return std::make_unique<Unsatisfiable>(); }
138
139 public:
140
141 bool implied_by(const Condition&) const override { return false; }
142
143 void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>>&) override { }
144
145 bool operator==(const Condition &o) const override { return is<const Unsatisfiable>(&o); }
146};
147
148struct Sortedness final : Condition
149{
150 enum Order { O_ASC, O_DESC, O_UNDEF /* undefined for single tuple results */ };
151
153
154 private:
156
157 public:
159
160 Sortedness() = default;
161 explicit Sortedness(const Sortedness&) = default;
162 Sortedness(Sortedness&&) = default;
163
164 private:
165 std::unique_ptr<Condition> clone() const override { return std::make_unique<Sortedness>(orders_); }
166
167 public:
168 order_t & orders() { return orders_; }
169 const order_t & orders() const { return orders_; }
170
171 bool implied_by(const Condition &o) const override {
172 auto other = cast<const Sortedness>(&o);
173 if (not other) return false;
174
175 for (auto this_it = this->orders_.begin(); this_it != this->orders_.end(); ++this_it) {
176 const auto other_it = other->orders_.find(this_it->first);
177 if (other_it == other->orders_.cend())
178 return false; // attribute not found
179 if (other_it->second == O_UNDEF or this_it->second == O_UNDEF)
180 continue; // sort order undefined implies attribute order does not matter
181 if (std::distance(this_it, this->orders_.begin()) != std::distance(other_it, other->orders_.cbegin()))
182 return false; // different attribute order
183 if (this_it->second != other_it->second)
184 return false; // opposite sort order
185 }
186 return true;
187 }
188
189 void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>> &old2new) override {
191 }
192
193 bool operator==(const Condition &o) const override {
194 auto other = cast<const Sortedness>(&o);
195 if (not other) return false;
196 return this->orders_ == other->orders_;
197 }
198};
199
201{
202 private:
203 std::size_t num_simd_lanes_;
204
205 public:
207
208 SIMD() = default;
209 explicit SIMD(const SIMD&) = default;
210 SIMD(SIMD&&) = default;
211
212 private:
213 std::unique_ptr<Condition> clone() const override { return std::make_unique<SIMD>(num_simd_lanes_); }
214
215 public:
216 std::size_t num_simd_lanes() const { return num_simd_lanes_; }
217
218 bool implied_by(const Condition &o) const override {
219 auto other = cast<const SIMD>(&o);
220 if (not other) return false;
221 return this->num_simd_lanes_ == other->num_simd_lanes_;
222 }
223
224 void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>>&) override { }
225
226 bool operator==(const Condition &o) const override {
227 auto other = cast<const SIMD>(&o);
228 if (not other) return false;
229 return this->num_simd_lanes_ == other->num_simd_lanes_;
230 }
231};
232
233struct NoSIMD final : SIMD
234{
235 explicit NoSIMD() : SIMD(1) { }
236};
237
238struct Predicated final : Condition
239{
240 private:
242
243 public:
245
246 Predicated() = default;
247 explicit Predicated(const Predicated&) = default;
248 Predicated(Predicated&&) = default;
249
250 private:
251 std::unique_ptr<Condition> clone() const override { return std::make_unique<Predicated>(predicated_); }
252
253 public:
254 bool predicated() const { return predicated_; }
255
256 bool implied_by(const Condition &o) const override {
257 auto other = cast<const Predicated>(&o);
258 if (not other) return false;
259 return other->predicated_ == this->predicated_;
260 }
261
262 void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>>&) override { }
263
264 bool operator==(const Condition &o) const override {
265 auto other = cast<const Predicated>(&o);
266 if (not other) return false;
267 return this->predicated_ == other->predicated_;
268 }
269};
270
272{
273 private:
275 std::unordered_map<std::type_index, std::unique_ptr<Condition>> type2cond_;
276
277 public:
278 ConditionSet() = default;
279 explicit ConditionSet(const ConditionSet &other) {
280 for (auto &p : other.type2cond_)
281 this->type2cond_.emplace(p.first, p.second->clone());
282 }
284
286
287 template<typename Cond>
288 requires std::is_base_of_v<Condition, Cond>
289 void add_condition(Cond &&cond) {
290 auto p = std::make_unique<Cond>(std::forward<Cond>(cond)); // move-construct on heap
291 auto [it, res] = type2cond_.try_emplace(typeid(Cond), std::move(p));
292 if (not res)
293 throw invalid_argument("Condition of that type already exists in the ConditionSet");
294 }
295
296 template<typename Cond>
297 requires std::is_base_of_v<Condition, Cond>
298 void add_or_replace_condition(Cond &&cond) {
299 auto p = std::make_unique<Cond>(std::forward<Cond>(cond)); // move-construct on heap
300 type2cond_.insert_or_assign(typeid(Cond), std::move(p));
301 }
302
303 template<typename Cond>
304 requires std::is_base_of_v<Condition, Cond>
305 Cond & get_condition() {
306 auto it = type2cond_.find(typeid(Cond));
307 M_insist(it != type2cond_.cend(), "condition not found");
308 return as<Cond>(*it->second);
309 }
310 template<typename Cond>
311 requires std::is_base_of_v<Condition, Cond>
312 const Cond & get_condition() const { return const_cast<ConditionSet*>(this)->get_condition<Cond>(); }
313
314 bool empty() const { return type2cond_.empty(); }
315
316 bool implied_by(const ConditionSet &other) const;
317
318 void project_and_rename(const std::vector<std::pair<Schema::Identifier, Schema::Identifier>> &old2new);
319
320 bool operator==(const ConditionSet &other) const;
321 bool operator!=(const ConditionSet &other) const { return not operator==(other); }
322
324};
325
326
327}
#define id(X)
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
uint64_t murmur3_64(uint64_t v)
This function implements the 64-bit finalizer of Murmur3_x64 by Austin Appleby, available at https://...
Definition: fn.hpp:466
and
Definition: enum_ops.hpp:12
std::size_t operator()(const Schema::Identifier &id) const
Definition: Condition.hpp:23
auto find(const Schema::Identifier &id) const
Definition: Condition.hpp:61
std::conditional_t< Ordered, std::vector< std::pair< Schema::Identifier, Property > >, std::unordered_map< Schema::Identifier, Property, IdentifierHash > > map_t
Definition: Condition.hpp:31
void merge(ConditionPropertyMap &other)
Definition: Condition.hpp:48
void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &old2new)
Definition: Condition.hpp:73
void add(Schema::Identifier id, Property P)
Definition: Condition.hpp:36
bool operator==(const ConditionPropertyMap &other) const
Definition: Condition.hpp:94
std::unordered_map< std::type_index, std::unique_ptr< Condition > > type2cond_
‍assigns a unique identifier to each type of Condition
Definition: Condition.hpp:275
bool empty() const
Definition: Condition.hpp:314
ConditionSet(ConditionSet &&)=default
Cond & get_condition()
Definition: Condition.hpp:305
bool operator==(const ConditionSet &other) const
Definition: Condition.cpp:25
static ConditionSet Make_Unsatisfiable()
Definition: Condition.hpp:323
void add_condition(Cond &&cond)
Definition: Condition.hpp:289
ConditionSet(const ConditionSet &other)
Definition: Condition.hpp:279
void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &old2new)
Definition: Condition.cpp:19
bool implied_by(const ConditionSet &other) const
Definition: Condition.cpp:7
ConditionSet & operator=(ConditionSet &&)=default
const Cond & get_condition() const
Definition: Condition.hpp:312
ConditionSet()=default
bool operator!=(const ConditionSet &other) const
Definition: Condition.hpp:321
void add_or_replace_condition(Cond &&cond)
Definition: Condition.hpp:298
virtual bool implied_by(const Condition &other) const =0
Checks whether this Condition is implied by other.
virtual ~Condition()
Definition: Condition.hpp:111
virtual void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &old2new)=0
Inform this Condition that Identifiers were simultaneously projected and renamed according to the map...
virtual std::unique_ptr< Condition > clone() const =0
Creates and returns a deep copy of this.
bool operator!=(const Condition &other) const
Definition: Condition.hpp:127
virtual bool operator==(const Condition &other) const =0
Predicated()=default
bool implied_by(const Condition &o) const override
Checks whether this Condition is implied by other.
Definition: Condition.hpp:256
Predicated(const Predicated &)=default
std::unique_ptr< Condition > clone() const override
Creates and returns a deep copy of this.
Definition: Condition.hpp:251
void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &) override
Inform this Condition that Identifiers were simultaneously projected and renamed according to the map...
Definition: Condition.hpp:262
Predicated(bool predicated)
Definition: Condition.hpp:244
Predicated(Predicated &&)=default
bool predicated() const
Definition: Condition.hpp:254
bool operator==(const Condition &o) const override
Definition: Condition.hpp:264
bool operator==(const Condition &o) const override
Definition: Condition.hpp:226
void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &) override
Inform this Condition that Identifiers were simultaneously projected and renamed according to the map...
Definition: Condition.hpp:224
std::unique_ptr< Condition > clone() const override
Creates and returns a deep copy of this.
Definition: Condition.hpp:213
std::size_t num_simd_lanes_
Definition: Condition.hpp:203
SIMD(const SIMD &)=default
SIMD(std::size_t num_simd_lanes)
Definition: Condition.hpp:206
SIMD(SIMD &&)=default
bool implied_by(const Condition &o) const override
Checks whether this Condition is implied by other.
Definition: Condition.hpp:218
std::size_t num_simd_lanes() const
Definition: Condition.hpp:216
SIMD()=default
An Identifier is composed of a name and an optional prefix.
Definition: Schema.hpp:42
void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &old2new) override
Inform this Condition that Identifiers were simultaneously projected and renamed according to the map...
Definition: Condition.hpp:189
bool implied_by(const Condition &o) const override
Checks whether this Condition is implied by other.
Definition: Condition.hpp:171
Sortedness(const Sortedness &)=default
Sortedness(order_t orders)
Definition: Condition.hpp:158
order_t orders_
Definition: Condition.hpp:155
const order_t & orders() const
Definition: Condition.hpp:169
Sortedness()=default
Sortedness(Sortedness &&)=default
std::unique_ptr< Condition > clone() const override
Creates and returns a deep copy of this.
Definition: Condition.hpp:165
order_t & orders()
Definition: Condition.hpp:168
bool operator==(const Condition &o) const override
Definition: Condition.hpp:193
void project_and_rename(const std::vector< std::pair< Schema::Identifier, Schema::Identifier > > &) override
Inform this Condition that Identifiers were simultaneously projected and renamed according to the map...
Definition: Condition.hpp:143
Unsatisfiable()=default
std::unique_ptr< Condition > clone() const override
Creates and returns a deep copy of this.
Definition: Condition.hpp:137
Unsatisfiable(Unsatisfiable &&)=default
Unsatisfiable(const Unsatisfiable &)=default
bool operator==(const Condition &o) const override
Definition: Condition.hpp:145
bool implied_by(const Condition &) const override
Checks whether this Condition is implied by other.
Definition: Condition.hpp:141
Signals that an argument to a function of method was invalid.
Definition: exception.hpp:37