added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / query.hpp
diff --git a/iOS/Pods/Realm/include/core/realm/query.hpp b/iOS/Pods/Realm/include/core/realm/query.hpp
new file mode 100644 (file)
index 0000000..9964264
--- /dev/null
@@ -0,0 +1,475 @@
+/*************************************************************************
+ *
+ * Copyright 2016 Realm Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **************************************************************************/
+
+#ifndef REALM_QUERY_HPP
+#define REALM_QUERY_HPP
+
+#include <cstdint>
+#include <cstdio>
+#include <climits>
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#define REALM_MULTITHREAD_QUERY 0
+
+#if REALM_MULTITHREAD_QUERY
+// FIXME: Use our C++ thread abstraction API since it provides a much
+// higher level of encapsulation and safety.
+#include <pthread.h>
+#endif
+
+#include <realm/views.hpp>
+#include <realm/table_ref.hpp>
+#include <realm/binary_data.hpp>
+#include <realm/olddatetime.hpp>
+#include <realm/handover_defs.hpp>
+#include <realm/link_view_fwd.hpp>
+#include <realm/descriptor_fwd.hpp>
+#include <realm/row.hpp>
+
+namespace realm {
+
+
+// Pre-declarations
+class ParentNode;
+class Table;
+class TableView;
+class TableViewBase;
+class ConstTableView;
+class Array;
+class Expression;
+class SequentialGetterBase;
+class Group;
+
+namespace metrics {
+class QueryInfo;
+}
+
+struct QueryGroup {
+    enum class State {
+        Default,
+        OrCondition,
+        OrConditionChildren,
+    };
+
+    QueryGroup() = default;
+
+    QueryGroup(const QueryGroup&);
+    QueryGroup& operator=(const QueryGroup&);
+
+    QueryGroup(QueryGroup&&) = default;
+    QueryGroup& operator=(QueryGroup&&) = default;
+
+    QueryGroup(const QueryGroup&, QueryNodeHandoverPatches&);
+
+    std::unique_ptr<ParentNode> m_root_node;
+
+    bool m_pending_not = false;
+    size_t m_subtable_column = not_found;
+    State m_state = State::Default;
+};
+
+class Query final {
+public:
+    Query(const Table& table, TableViewBase* tv = nullptr);
+    Query(const Table& table, std::unique_ptr<TableViewBase>);
+    Query(const Table& table, const LinkViewRef& lv);
+    Query();
+    Query(std::unique_ptr<Expression>);
+    ~Query() noexcept;
+
+    Query(const Query& copy);
+    Query& operator=(const Query& source);
+
+    Query(Query&&);
+    Query& operator=(Query&&);
+
+    // Find links that point to a specific target row
+    Query& links_to(size_t column_ndx, const ConstRow& target_row);
+
+    // Conditions: null
+    Query& equal(size_t column_ndx, null);
+    Query& not_equal(size_t column_ndx, null);
+
+    // Conditions: int64_t
+    Query& equal(size_t column_ndx, int64_t value);
+    Query& not_equal(size_t column_ndx, int64_t value);
+    Query& greater(size_t column_ndx, int64_t value);
+    Query& greater_equal(size_t column_ndx, int64_t value);
+    Query& less(size_t column_ndx, int64_t value);
+    Query& less_equal(size_t column_ndx, int64_t value);
+    Query& between(size_t column_ndx, int64_t from, int64_t to);
+
+    // Conditions: int (we need those because conversion from '1234' is ambiguous with float/double)
+    Query& equal(size_t column_ndx, int value);
+    Query& not_equal(size_t column_ndx, int value);
+    Query& greater(size_t column_ndx, int value);
+    Query& greater_equal(size_t column_ndx, int value);
+    Query& less(size_t column_ndx, int value);
+    Query& less_equal(size_t column_ndx, int value);
+    Query& between(size_t column_ndx, int from, int to);
+
+    // Conditions: 2 int columns
+    Query& equal_int(size_t column_ndx1, size_t column_ndx2);
+    Query& not_equal_int(size_t column_ndx1, size_t column_ndx2);
+    Query& greater_int(size_t column_ndx1, size_t column_ndx2);
+    Query& less_int(size_t column_ndx1, size_t column_ndx2);
+    Query& greater_equal_int(size_t column_ndx1, size_t column_ndx2);
+    Query& less_equal_int(size_t column_ndx1, size_t column_ndx2);
+
+    // Conditions: float
+    Query& equal(size_t column_ndx, float value);
+    Query& not_equal(size_t column_ndx, float value);
+    Query& greater(size_t column_ndx, float value);
+    Query& greater_equal(size_t column_ndx, float value);
+    Query& less(size_t column_ndx, float value);
+    Query& less_equal(size_t column_ndx, float value);
+    Query& between(size_t column_ndx, float from, float to);
+
+    // Conditions: 2 float columns
+    Query& equal_float(size_t column_ndx1, size_t column_ndx2);
+    Query& not_equal_float(size_t column_ndx1, size_t column_ndx2);
+    Query& greater_float(size_t column_ndx1, size_t column_ndx2);
+    Query& greater_equal_float(size_t column_ndx1, size_t column_ndx2);
+    Query& less_float(size_t column_ndx1, size_t column_ndx2);
+    Query& less_equal_float(size_t column_ndx1, size_t column_ndx2);
+
+    // Conditions: double
+    Query& equal(size_t column_ndx, double value);
+    Query& not_equal(size_t column_ndx, double value);
+    Query& greater(size_t column_ndx, double value);
+    Query& greater_equal(size_t column_ndx, double value);
+    Query& less(size_t column_ndx, double value);
+    Query& less_equal(size_t column_ndx, double value);
+    Query& between(size_t column_ndx, double from, double to);
+
+    // Conditions: 2 double columns
+    Query& equal_double(size_t column_ndx1, size_t column_ndx2);
+    Query& not_equal_double(size_t column_ndx1, size_t column_ndx2);
+    Query& greater_double(size_t column_ndx1, size_t column_ndx2);
+    Query& greater_equal_double(size_t column_ndx1, size_t column_ndx2);
+    Query& less_double(size_t column_ndx1, size_t column_ndx2);
+    Query& less_equal_double(size_t column_ndx1, size_t column_ndx2);
+
+    // Conditions: timestamp
+    Query& equal(size_t column_ndx, Timestamp value);
+    Query& not_equal(size_t column_ndx, Timestamp value);
+    Query& greater(size_t column_ndx, Timestamp value);
+    Query& greater_equal(size_t column_ndx, Timestamp value);
+    Query& less_equal(size_t column_ndx, Timestamp value);
+    Query& less(size_t column_ndx, Timestamp value);
+
+    // Conditions: size
+    Query& size_equal(size_t column_ndx, int64_t value);
+    Query& size_not_equal(size_t column_ndx, int64_t value);
+    Query& size_greater(size_t column_ndx, int64_t value);
+    Query& size_greater_equal(size_t column_ndx, int64_t value);
+    Query& size_less_equal(size_t column_ndx, int64_t value);
+    Query& size_less(size_t column_ndx, int64_t value);
+    Query& size_between(size_t column_ndx, int64_t from, int64_t to);
+
+    // Conditions: bool
+    Query& equal(size_t column_ndx, bool value);
+
+    // Conditions: date
+    Query& equal_olddatetime(size_t column_ndx, OldDateTime value)
+    {
+        return equal(column_ndx, int64_t(value.get_olddatetime()));
+    }
+    Query& not_equal_olddatetime(size_t column_ndx, OldDateTime value)
+    {
+        return not_equal(column_ndx, int64_t(value.get_olddatetime()));
+    }
+    Query& greater_olddatetime(size_t column_ndx, OldDateTime value)
+    {
+        return greater(column_ndx, int64_t(value.get_olddatetime()));
+    }
+    Query& greater_equal_olddatetime(size_t column_ndx, OldDateTime value)
+    {
+        return greater_equal(column_ndx, int64_t(value.get_olddatetime()));
+    }
+    Query& less_olddatetime(size_t column_ndx, OldDateTime value)
+    {
+        return less(column_ndx, int64_t(value.get_olddatetime()));
+    }
+    Query& less_equal_olddatetime(size_t column_ndx, OldDateTime value)
+    {
+        return less_equal(column_ndx, int64_t(value.get_olddatetime()));
+    }
+    Query& between_olddatetime(size_t column_ndx, OldDateTime from, OldDateTime to)
+    {
+        return between(column_ndx, int64_t(from.get_olddatetime()), int64_t(to.get_olddatetime()));
+    }
+
+    // Conditions: strings
+    Query& equal(size_t column_ndx, StringData value, bool case_sensitive = true);
+    Query& not_equal(size_t column_ndx, StringData value, bool case_sensitive = true);
+    Query& begins_with(size_t column_ndx, StringData value, bool case_sensitive = true);
+    Query& ends_with(size_t column_ndx, StringData value, bool case_sensitive = true);
+    Query& contains(size_t column_ndx, StringData value, bool case_sensitive = true);
+    Query& like(size_t column_ndx, StringData value, bool case_sensitive = true);
+
+    // These are shortcuts for equal(StringData(c_str)) and
+    // not_equal(StringData(c_str)), and are needed to avoid unwanted
+    // implicit conversion of char* to bool.
+    Query& equal(size_t column_ndx, const char* c_str, bool case_sensitive = true);
+    Query& not_equal(size_t column_ndx, const char* c_str, bool case_sensitive = true);
+
+    // Conditions: binary data
+    Query& equal(size_t column_ndx, BinaryData value);
+    Query& not_equal(size_t column_ndx, BinaryData value);
+    Query& begins_with(size_t column_ndx, BinaryData value);
+    Query& ends_with(size_t column_ndx, BinaryData value);
+    Query& contains(size_t column_ndx, BinaryData value);
+
+    // Negation
+    Query& Not();
+
+    // Grouping
+    Query& group();
+    Query& end_group();
+    Query& subtable(size_t column);
+    Query& end_subtable();
+    Query& Or();
+
+    Query& and_query(const Query& q);
+    Query& and_query(Query&& q);
+    Query operator||(const Query& q);
+    Query operator&&(const Query& q);
+    Query operator!();
+
+
+    // Searching
+    size_t find(size_t begin_at_table_row = size_t(0));
+    TableView find_all(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1));
+    ConstTableView find_all(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const;
+
+    // Aggregates
+    size_t count(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const;
+
+    int64_t sum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                    size_t limit = size_t(-1)) const;
+
+    double average_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                       size_t limit = size_t(-1)) const;
+
+    int64_t maximum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                        size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
+
+    int64_t minimum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                        size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
+
+    double sum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                     size_t limit = size_t(-1)) const;
+
+    double average_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                         size_t limit = size_t(-1)) const;
+
+    float maximum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                        size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
+
+    float minimum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                        size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
+
+    double sum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                      size_t limit = size_t(-1)) const;
+
+    double average_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                          size_t limit = size_t(-1)) const;
+
+    double maximum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                          size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
+
+    double minimum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                          size_t limit = size_t(-1), size_t* return_ndx = nullptr) const;
+
+    OldDateTime maximum_olddatetime(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0,
+                                    size_t end = size_t(-1), size_t limit = size_t(-1),
+                                    size_t* return_ndx = nullptr) const;
+
+    OldDateTime minimum_olddatetime(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0,
+                                    size_t end = size_t(-1), size_t limit = size_t(-1),
+                                    size_t* return_ndx = nullptr) const;
+
+    Timestamp maximum_timestamp(size_t column_ndx, size_t* return_ndx, size_t start = 0, size_t end = size_t(-1),
+                                size_t limit = size_t(-1));
+
+    Timestamp minimum_timestamp(size_t column_ndx, size_t* return_ndx, size_t start = 0, size_t end = size_t(-1),
+                                size_t limit = size_t(-1));
+
+    // Deletion
+    size_t remove();
+
+#if REALM_MULTITHREAD_QUERY
+    // Multi-threading
+    TableView find_all_multi(size_t start = 0, size_t end = size_t(-1));
+    ConstTableView find_all_multi(size_t start = 0, size_t end = size_t(-1)) const;
+    int set_threads(unsigned int threadcount);
+#endif
+
+    const TableRef& get_table()
+    {
+        return m_table;
+    }
+
+    // True if matching rows are guaranteed to be returned in table order.
+    bool produces_results_in_table_order() const
+    {
+        return !m_view;
+    }
+
+    // Calls sync_if_needed on the restricting view, if present.
+    // Returns the current version of the table(s) this query depends on,
+    // or util::none if the query is not associated with a table.
+    util::Optional<uint_fast64_t> sync_view_if_needed() const;
+
+    std::string validate();
+
+    std::string get_description() const;
+
+private:
+    Query(Table& table, TableViewBase* tv = nullptr);
+    void create();
+
+    void init() const;
+    size_t find_internal(size_t start = 0, size_t end = size_t(-1)) const;
+    size_t peek_tablerow(size_t row) const;
+    void handle_pending_not();
+    void set_table(TableRef tr);
+
+public:
+    using HandoverPatch = QueryHandoverPatch;
+
+    std::unique_ptr<Query> clone_for_handover(std::unique_ptr<HandoverPatch>& patch, ConstSourcePayload mode) const
+    {
+        patch.reset(new HandoverPatch);
+        return std::make_unique<Query>(*this, *patch, mode);
+    }
+
+    std::unique_ptr<Query> clone_for_handover(std::unique_ptr<HandoverPatch>& patch, MutableSourcePayload mode)
+    {
+        patch.reset(new HandoverPatch);
+        return std::make_unique<Query>(*this, *patch, mode);
+    }
+
+    void apply_and_consume_patch(std::unique_ptr<HandoverPatch>& patch, Group& dest_group)
+    {
+        apply_patch(*patch, dest_group);
+        patch.reset();
+    }
+
+    void apply_patch(HandoverPatch& patch, Group& dest_group);
+    Query(const Query& source, HandoverPatch& patch, ConstSourcePayload mode);
+    Query(Query& source, HandoverPatch& patch, MutableSourcePayload mode);
+
+private:
+    void fetch_descriptor();
+
+    void add_expression_node(std::unique_ptr<Expression>);
+
+    template <class ColumnType>
+    Query& equal(size_t column_ndx1, size_t column_ndx2);
+
+    template <class ColumnType>
+    Query& less(size_t column_ndx1, size_t column_ndx2);
+
+    template <class ColumnType>
+    Query& less_equal(size_t column_ndx1, size_t column_ndx2);
+
+    template <class ColumnType>
+    Query& greater(size_t column_ndx1, size_t column_ndx2);
+
+    template <class ColumnType>
+    Query& greater_equal(size_t column_ndx1, size_t column_ndx2);
+
+    template <class ColumnType>
+    Query& not_equal(size_t column_ndx1, size_t column_ndx2);
+
+    template <typename TConditionFunction, class T>
+    Query& add_condition(size_t column_ndx, T value);
+
+    template <typename TConditionFunction>
+    Query& add_size_condition(size_t column_ndx, int64_t value);
+
+    template <typename T, bool Nullable>
+    double average(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1),
+                   size_t limit = size_t(-1)) const;
+
+    template <Action action, typename T, typename R, class ColClass>
+    R aggregate(R (ColClass::*method)(size_t, size_t, size_t, size_t*) const, size_t column_ndx, size_t* resultcount,
+                size_t start, size_t end, size_t limit, size_t* return_ndx = nullptr) const;
+
+    void aggregate_internal(Action TAction, DataType TSourceColumn, bool nullable, ParentNode* pn, QueryStateBase* st,
+                            size_t start, size_t end, SequentialGetterBase* source_column) const;
+
+    void find_all(TableViewBase& tv, size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const;
+    void delete_nodes() noexcept;
+
+    bool has_conditions() const
+    {
+        return m_groups.size() > 0 && m_groups[0].m_root_node;
+    }
+    ParentNode* root_node() const
+    {
+        REALM_ASSERT(m_groups.size());
+        return m_groups[0].m_root_node.get();
+    }
+
+    void add_node(std::unique_ptr<ParentNode>);
+
+    friend class Table;
+    friend class TableViewBase;
+    friend class metrics::QueryInfo;
+
+    std::string error_code;
+
+    std::vector<QueryGroup> m_groups;
+
+    // Used to access schema while building query:
+    std::vector<size_t> m_subtable_path;
+
+    ConstDescriptorRef m_current_descriptor;
+    TableRef m_table;
+
+    // points to the base class of the restricting view. If the restricting
+    // view is a link view, m_source_link_view is non-zero. If it is a table view,
+    // m_source_table_view is non-zero.
+    RowIndexes* m_view = nullptr;
+
+    // At most one of these can be non-zero, and if so the non-zero one indicates the restricting view.
+    LinkViewRef m_source_link_view;               // link views are refcounted and shared.
+    TableViewBase* m_source_table_view = nullptr; // table views are not refcounted, and not owned by the query.
+    std::unique_ptr<TableViewBase> m_owned_source_table_view; // <--- except when indicated here
+};
+
+// Implementation:
+
+inline Query& Query::equal(size_t column_ndx, const char* c_str, bool case_sensitive)
+{
+    return equal(column_ndx, StringData(c_str), case_sensitive);
+}
+
+inline Query& Query::not_equal(size_t column_ndx, const char* c_str, bool case_sensitive)
+{
+    return not_equal(column_ndx, StringData(c_str), case_sensitive);
+}
+
+} // namespace realm
+
+#endif // REALM_QUERY_HPP