1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 **************************************************************************/
19 #ifndef REALM_QUERY_HPP
20 #define REALM_QUERY_HPP
29 #define REALM_MULTITHREAD_QUERY 0
31 #if REALM_MULTITHREAD_QUERY
32 // FIXME: Use our C++ thread abstraction API since it provides a much
33 // higher level of encapsulation and safety.
37 #include <realm/views.hpp>
38 #include <realm/table_ref.hpp>
39 #include <realm/binary_data.hpp>
40 #include <realm/olddatetime.hpp>
41 #include <realm/handover_defs.hpp>
42 #include <realm/link_view_fwd.hpp>
43 #include <realm/descriptor_fwd.hpp>
44 #include <realm/row.hpp>
57 class SequentialGetterBase;
71 QueryGroup() = default;
73 QueryGroup(const QueryGroup&);
74 QueryGroup& operator=(const QueryGroup&);
76 QueryGroup(QueryGroup&&) = default;
77 QueryGroup& operator=(QueryGroup&&) = default;
79 QueryGroup(const QueryGroup&, QueryNodeHandoverPatches&);
81 std::unique_ptr<ParentNode> m_root_node;
83 bool m_pending_not = false;
84 size_t m_subtable_column = not_found;
85 State m_state = State::Default;
90 Query(const Table& table, TableViewBase* tv = nullptr);
91 Query(const Table& table, std::unique_ptr<TableViewBase>);
92 Query(const Table& table, const LinkViewRef& lv);
94 Query(std::unique_ptr<Expression>);
97 Query(const Query& copy);
98 Query& operator=(const Query& source);
101 Query& operator=(Query&&);
103 // Find links that point to a specific target row
104 Query& links_to(size_t column_ndx, const ConstRow& target_row);
107 Query& equal(size_t column_ndx, null);
108 Query& not_equal(size_t column_ndx, null);
110 // Conditions: int64_t
111 Query& equal(size_t column_ndx, int64_t value);
112 Query& not_equal(size_t column_ndx, int64_t value);
113 Query& greater(size_t column_ndx, int64_t value);
114 Query& greater_equal(size_t column_ndx, int64_t value);
115 Query& less(size_t column_ndx, int64_t value);
116 Query& less_equal(size_t column_ndx, int64_t value);
117 Query& between(size_t column_ndx, int64_t from, int64_t to);
119 // Conditions: int (we need those because conversion from '1234' is ambiguous with float/double)
120 Query& equal(size_t column_ndx, int value);
121 Query& not_equal(size_t column_ndx, int value);
122 Query& greater(size_t column_ndx, int value);
123 Query& greater_equal(size_t column_ndx, int value);
124 Query& less(size_t column_ndx, int value);
125 Query& less_equal(size_t column_ndx, int value);
126 Query& between(size_t column_ndx, int from, int to);
128 // Conditions: 2 int columns
129 Query& equal_int(size_t column_ndx1, size_t column_ndx2);
130 Query& not_equal_int(size_t column_ndx1, size_t column_ndx2);
131 Query& greater_int(size_t column_ndx1, size_t column_ndx2);
132 Query& less_int(size_t column_ndx1, size_t column_ndx2);
133 Query& greater_equal_int(size_t column_ndx1, size_t column_ndx2);
134 Query& less_equal_int(size_t column_ndx1, size_t column_ndx2);
137 Query& equal(size_t column_ndx, float value);
138 Query& not_equal(size_t column_ndx, float value);
139 Query& greater(size_t column_ndx, float value);
140 Query& greater_equal(size_t column_ndx, float value);
141 Query& less(size_t column_ndx, float value);
142 Query& less_equal(size_t column_ndx, float value);
143 Query& between(size_t column_ndx, float from, float to);
145 // Conditions: 2 float columns
146 Query& equal_float(size_t column_ndx1, size_t column_ndx2);
147 Query& not_equal_float(size_t column_ndx1, size_t column_ndx2);
148 Query& greater_float(size_t column_ndx1, size_t column_ndx2);
149 Query& greater_equal_float(size_t column_ndx1, size_t column_ndx2);
150 Query& less_float(size_t column_ndx1, size_t column_ndx2);
151 Query& less_equal_float(size_t column_ndx1, size_t column_ndx2);
153 // Conditions: double
154 Query& equal(size_t column_ndx, double value);
155 Query& not_equal(size_t column_ndx, double value);
156 Query& greater(size_t column_ndx, double value);
157 Query& greater_equal(size_t column_ndx, double value);
158 Query& less(size_t column_ndx, double value);
159 Query& less_equal(size_t column_ndx, double value);
160 Query& between(size_t column_ndx, double from, double to);
162 // Conditions: 2 double columns
163 Query& equal_double(size_t column_ndx1, size_t column_ndx2);
164 Query& not_equal_double(size_t column_ndx1, size_t column_ndx2);
165 Query& greater_double(size_t column_ndx1, size_t column_ndx2);
166 Query& greater_equal_double(size_t column_ndx1, size_t column_ndx2);
167 Query& less_double(size_t column_ndx1, size_t column_ndx2);
168 Query& less_equal_double(size_t column_ndx1, size_t column_ndx2);
170 // Conditions: timestamp
171 Query& equal(size_t column_ndx, Timestamp value);
172 Query& not_equal(size_t column_ndx, Timestamp value);
173 Query& greater(size_t column_ndx, Timestamp value);
174 Query& greater_equal(size_t column_ndx, Timestamp value);
175 Query& less_equal(size_t column_ndx, Timestamp value);
176 Query& less(size_t column_ndx, Timestamp value);
179 Query& size_equal(size_t column_ndx, int64_t value);
180 Query& size_not_equal(size_t column_ndx, int64_t value);
181 Query& size_greater(size_t column_ndx, int64_t value);
182 Query& size_greater_equal(size_t column_ndx, int64_t value);
183 Query& size_less_equal(size_t column_ndx, int64_t value);
184 Query& size_less(size_t column_ndx, int64_t value);
185 Query& size_between(size_t column_ndx, int64_t from, int64_t to);
188 Query& equal(size_t column_ndx, bool value);
191 Query& equal_olddatetime(size_t column_ndx, OldDateTime value)
193 return equal(column_ndx, int64_t(value.get_olddatetime()));
195 Query& not_equal_olddatetime(size_t column_ndx, OldDateTime value)
197 return not_equal(column_ndx, int64_t(value.get_olddatetime()));
199 Query& greater_olddatetime(size_t column_ndx, OldDateTime value)
201 return greater(column_ndx, int64_t(value.get_olddatetime()));
203 Query& greater_equal_olddatetime(size_t column_ndx, OldDateTime value)
205 return greater_equal(column_ndx, int64_t(value.get_olddatetime()));
207 Query& less_olddatetime(size_t column_ndx, OldDateTime value)
209 return less(column_ndx, int64_t(value.get_olddatetime()));
211 Query& less_equal_olddatetime(size_t column_ndx, OldDateTime value)
213 return less_equal(column_ndx, int64_t(value.get_olddatetime()));
215 Query& between_olddatetime(size_t column_ndx, OldDateTime from, OldDateTime to)
217 return between(column_ndx, int64_t(from.get_olddatetime()), int64_t(to.get_olddatetime()));
220 // Conditions: strings
221 Query& equal(size_t column_ndx, StringData value, bool case_sensitive = true);
222 Query& not_equal(size_t column_ndx, StringData value, bool case_sensitive = true);
223 Query& begins_with(size_t column_ndx, StringData value, bool case_sensitive = true);
224 Query& ends_with(size_t column_ndx, StringData value, bool case_sensitive = true);
225 Query& contains(size_t column_ndx, StringData value, bool case_sensitive = true);
226 Query& like(size_t column_ndx, StringData value, bool case_sensitive = true);
228 // These are shortcuts for equal(StringData(c_str)) and
229 // not_equal(StringData(c_str)), and are needed to avoid unwanted
230 // implicit conversion of char* to bool.
231 Query& equal(size_t column_ndx, const char* c_str, bool case_sensitive = true);
232 Query& not_equal(size_t column_ndx, const char* c_str, bool case_sensitive = true);
234 // Conditions: binary data
235 Query& equal(size_t column_ndx, BinaryData value);
236 Query& not_equal(size_t column_ndx, BinaryData value);
237 Query& begins_with(size_t column_ndx, BinaryData value);
238 Query& ends_with(size_t column_ndx, BinaryData value);
239 Query& contains(size_t column_ndx, BinaryData value);
247 Query& subtable(size_t column);
248 Query& end_subtable();
251 Query& and_query(const Query& q);
252 Query& and_query(Query&& q);
253 Query operator||(const Query& q);
254 Query operator&&(const Query& q);
259 size_t find(size_t begin_at_table_row = size_t(0));
260 TableView find_all(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1));
261 ConstTableView find_all(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const;
264 size_t count(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const;
266 int64_t sum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
267 size_t limit = size_t(-1)) const;
269 double average_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
270 size_t limit = size_t(-1)) const;
272 int64_t maximum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
273 size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
275 int64_t minimum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
276 size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
278 double sum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
279 size_t limit = size_t(-1)) const;
281 double average_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
282 size_t limit = size_t(-1)) const;
284 float maximum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
285 size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
287 float minimum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
288 size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
290 double sum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
291 size_t limit = size_t(-1)) const;
293 double average_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
294 size_t limit = size_t(-1)) const;
296 double maximum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
297 size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
299 double minimum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
300 size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
302 OldDateTime maximum_olddatetime(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0,
303 size_t end = size_t(-1), size_t limit = size_t(-1),
304 size_t* return_ndx = nullptr) const;
306 OldDateTime minimum_olddatetime(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0,
307 size_t end = size_t(-1), size_t limit = size_t(-1),
308 size_t* return_ndx = nullptr) const;
310 Timestamp maximum_timestamp(size_t column_ndx, size_t* return_ndx, size_t start = 0, size_t end = size_t(-1),
311 size_t limit = size_t(-1));
313 Timestamp minimum_timestamp(size_t column_ndx, size_t* return_ndx, size_t start = 0, size_t end = size_t(-1),
314 size_t limit = size_t(-1));
319 #if REALM_MULTITHREAD_QUERY
321 TableView find_all_multi(size_t start = 0, size_t end = size_t(-1));
322 ConstTableView find_all_multi(size_t start = 0, size_t end = size_t(-1)) const;
323 int set_threads(unsigned int threadcount);
326 const TableRef& get_table()
331 // True if matching rows are guaranteed to be returned in table order.
332 bool produces_results_in_table_order() const
337 // Calls sync_if_needed on the restricting view, if present.
338 // Returns the current version of the table(s) this query depends on,
339 // or util::none if the query is not associated with a table.
340 util::Optional<uint_fast64_t> sync_view_if_needed() const;
342 std::string validate();
344 std::string get_description() const;
347 Query(Table& table, TableViewBase* tv = nullptr);
351 size_t find_internal(size_t start = 0, size_t end = size_t(-1)) const;
352 size_t peek_tablerow(size_t row) const;
353 void handle_pending_not();
354 void set_table(TableRef tr);
357 using HandoverPatch = QueryHandoverPatch;
359 std::unique_ptr<Query> clone_for_handover(std::unique_ptr<HandoverPatch>& patch, ConstSourcePayload mode) const
361 patch.reset(new HandoverPatch);
362 return std::make_unique<Query>(*this, *patch, mode);
365 std::unique_ptr<Query> clone_for_handover(std::unique_ptr<HandoverPatch>& patch, MutableSourcePayload mode)
367 patch.reset(new HandoverPatch);
368 return std::make_unique<Query>(*this, *patch, mode);
371 void apply_and_consume_patch(std::unique_ptr<HandoverPatch>& patch, Group& dest_group)
373 apply_patch(*patch, dest_group);
377 void apply_patch(HandoverPatch& patch, Group& dest_group);
378 Query(const Query& source, HandoverPatch& patch, ConstSourcePayload mode);
379 Query(Query& source, HandoverPatch& patch, MutableSourcePayload mode);
382 void fetch_descriptor();
384 void add_expression_node(std::unique_ptr<Expression>);
386 template <class ColumnType>
387 Query& equal(size_t column_ndx1, size_t column_ndx2);
389 template <class ColumnType>
390 Query& less(size_t column_ndx1, size_t column_ndx2);
392 template <class ColumnType>
393 Query& less_equal(size_t column_ndx1, size_t column_ndx2);
395 template <class ColumnType>
396 Query& greater(size_t column_ndx1, size_t column_ndx2);
398 template <class ColumnType>
399 Query& greater_equal(size_t column_ndx1, size_t column_ndx2);
401 template <class ColumnType>
402 Query& not_equal(size_t column_ndx1, size_t column_ndx2);
404 template <typename TConditionFunction, class T>
405 Query& add_condition(size_t column_ndx, T value);
407 template <typename TConditionFunction>
408 Query& add_size_condition(size_t column_ndx, int64_t value);
410 template <typename T, bool Nullable>
411 double average(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
412 size_t limit = size_t(-1)) const;
414 template <Action action, typename T, typename R, class ColClass>
415 R aggregate(R (ColClass::*method)(size_t, size_t, size_t, size_t*) const, size_t column_ndx, size_t* resultcount,
416 size_t start, size_t end, size_t limit, size_t* return_ndx = nullptr) const;
418 void aggregate_internal(Action TAction, DataType TSourceColumn, bool nullable, ParentNode* pn, QueryStateBase* st,
419 size_t start, size_t end, SequentialGetterBase* source_column) const;
421 void find_all(TableViewBase& tv, size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const;
422 void delete_nodes() noexcept;
424 bool has_conditions() const
426 return m_groups.size() > 0 && m_groups[0].m_root_node;
428 ParentNode* root_node() const
430 REALM_ASSERT(m_groups.size());
431 return m_groups[0].m_root_node.get();
434 void add_node(std::unique_ptr<ParentNode>);
437 friend class TableViewBase;
438 friend class metrics::QueryInfo;
440 std::string error_code;
442 std::vector<QueryGroup> m_groups;
444 // Used to access schema while building query:
445 std::vector<size_t> m_subtable_path;
447 ConstDescriptorRef m_current_descriptor;
450 // points to the base class of the restricting view. If the restricting
451 // view is a link view, m_source_link_view is non-zero. If it is a table view,
452 // m_source_table_view is non-zero.
453 RowIndexes* m_view = nullptr;
455 // At most one of these can be non-zero, and if so the non-zero one indicates the restricting view.
456 LinkViewRef m_source_link_view; // link views are refcounted and shared.
457 TableViewBase* m_source_table_view = nullptr; // table views are not refcounted, and not owned by the query.
458 std::unique_ptr<TableViewBase> m_owned_source_table_view; // <--- except when indicated here
463 inline Query& Query::equal(size_t column_ndx, const char* c_str, bool case_sensitive)
465 return equal(column_ndx, StringData(c_str), case_sensitive);
468 inline Query& Query::not_equal(size_t column_ndx, const char* c_str, bool case_sensitive)
470 return not_equal(column_ndx, StringData(c_str), case_sensitive);
475 #endif // REALM_QUERY_HPP