added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / sync / object.hpp
1 /*************************************************************************
2  *
3  * Copyright 2017 Realm Inc.
4  *
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_SYNC_OBJECT_HPP
20 #define REALM_SYNC_OBJECT_HPP
21
22 #include <realm/util/logger.hpp>
23 #include <realm/table_ref.hpp>
24 #include <realm/string_data.hpp>
25
26 #include <realm/sync/object_id.hpp>
27
28 #include <vector>
29
30 /// This file presents a convenience API for making changes to a Realm file that
31 /// adhere to the conventions of assigning stable IDs to every object.
32
33 namespace realm {
34
35 class Group;
36
37 namespace sync {
38
39 class SyncHistory;
40
41 static const char object_id_column_name[] = "!OID";
42 static const char array_value_column_name[] = "!ARRAY_VALUE"; // FIXME call Jorgen
43
44 struct TableInfoCache;
45
46 /// Determine whether the Group has a sync-type history, and therefore whether
47 /// it supports globally stable object IDs.
48 ///
49 /// The Group does not need to be in a transaction.
50 bool has_object_ids(const Group&);
51
52 /// Determine whether object IDs for objects without primary keys are globally
53 /// stable. This is true if and only if the Group has been in touch with the
54 /// server (or is the server), and will remain true forever thereafter.
55 ///
56 /// It is an error to call this function for groups that do not have object IDs
57 /// (i.e. where `has_object_ids()` returns false).
58 ///
59 /// The Group is assumed to be in a read transaction.
60 bool is_object_id_stability_achieved(const Group&);
61
62 /// Create a table with an object ID column.
63 ///
64 /// It is an error to add tables to Groups with a sync history type directly.
65 /// This function or related functions must be used instead.
66 ///
67 /// The resulting table will be born with 1 column, which is a column used
68 /// in the maintenance of object IDs.
69 ///
70 /// NOTE: The table name must begin with the prefix "class_" in accordance with
71 /// Object Store conventions.
72 ///
73 /// The Group must be in a write transaction.
74 TableRef create_table(Group&, StringData name);
75
76 /// Create a table with an object ID column and a primary key column.
77 ///
78 /// It is an error to add tables to Groups with a sync history type directly.
79 /// This function or related functions must be used instead.
80 ///
81 /// The resulting table will be born with 2 columns, which is a column used
82 /// in the maintenance of object IDs and the requested primary key column.
83 /// The primary key column must have either integer or string type, and it
84 /// will be given the name provided in the argument \a pk_column_name.
85 ///
86 /// The 'pk' metadata table is updated with information about the primary key
87 /// column. If the 'pk' table does not yet exist, it is created.
88 ///
89 /// Please note: The 'pk' metadata table will not be synchronized directly,
90 /// so subsequent updates to it will be lost (as they constitute schema-breaking
91 /// changes).
92 ///
93 /// NOTE: The table name must begin with the prefix "class_" in accordance with
94 /// Object Store conventions.
95 ///
96 /// The Group must be in a write transaction.
97 TableRef create_table_with_primary_key(Group&, StringData name, DataType pk_type,
98                                        StringData pk_column_name, bool nullable = false);
99
100 /// Create an array column with the specified element type.
101 ///
102 /// The result will be a column of type type_Table with one subcolumn named
103 /// "!ARRAY_VALUE" of the specified element type.
104 ///
105 /// Return the column index of the inserted array column.
106 size_t add_array_column(Table&, DataType element_type, StringData column_name);
107
108
109 //@{
110 /// Calculate the object ID from the argument, where the argument is a primary
111 /// key value.
112 ObjectID object_id_for_primary_key(StringData);
113 ObjectID object_id_for_primary_key(util::Optional<int64_t>);
114 //@}
115
116 /// Determine whether it is safe to call `object_id_for_row()` on tables without
117 /// primary keys. If the table has a primary key, always returns true.
118 bool has_globally_stable_object_ids(const Table&);
119
120 bool table_has_primary_key(const TableInfoCache&, const Table&);
121
122 /// Get the globally unique object ID for the row.
123 ///
124 /// If the table has a primary key, this is guaranteed to succeed. Otherwise, if
125 /// the server has not been contacted yet (`has_globally_stable_object_ids()`
126 /// returns false), an exception is thrown.
127 ObjectID object_id_for_row(const TableInfoCache&, const Table&, size_t);
128
129 /// Get the index of the row with the object ID.
130 ///
131 /// \returns realm::npos if the object does not exist in the table.
132 size_t row_for_object_id(const TableInfoCache&, const Table&, ObjectID);
133
134 //@{
135 /// Add a row to the table and populate the object ID with an appropriate value.
136 ///
137 /// In the variant which takes an ObjectID parameter, a check is performed to see
138 /// if the object already exists. If it does, the row index of the existing object
139 /// is returned.
140 ///
141 /// If the table has a primary key column, an exception is thrown.
142 ///
143 /// \returns the row index of the object.
144 size_t create_object(const TableInfoCache&, Table&);
145 size_t create_object(const TableInfoCache&, Table&, ObjectID);
146 //@}
147
148 //@{
149 /// Create an object with a primary key value and populate the object ID with an
150 /// appropriate value.
151 ///
152 /// If the table does not have a primary key column (as indicated by the Object
153 /// Store's metadata in the special "pk" table), or the type of the primary key
154 /// column does not match the argument provided, an exception is thrown.
155 ///
156 /// The primary key column's value is populated with the appropriate
157 /// `set_int_unique()`, `set_string_unique()`, or `set_null_unique()` method
158 /// called on \a table.
159 ///
160 /// If an object with the given primary key value already exists, its row number
161 /// is returned without creating any new objects.
162 ///
163 /// These are convenience functions, equivalent to the following:
164 ///   - Add an empty row to the table.
165 ///   - Obtain an `ObjectID` with `object_id_for_primary_key()`.
166 ///   - Obtain a local object ID with `global_to_local_object_id()`.
167 ///   - Store the local object ID in the object ID column.
168 ///   - Call `set_int_unique()`,`set_string_unique()`, or `set_null_unique()`
169 ///     to set the primary key value.
170 ///
171 /// \returns the row index of the created object.
172 size_t create_object_with_primary_key(const TableInfoCache&, Table&, util::Optional<int64_t> primary_key);
173 size_t create_object_with_primary_key(const TableInfoCache&, Table&, StringData primary_key);
174 //@}
175
176 struct TableInfoCache {
177     const Group& m_group;
178
179     // Implicit conversion deliberately allowed for the purpose of calling the above
180     // functions without constructing a cache manually.
181     TableInfoCache(const Group&);
182     TableInfoCache(TableInfoCache&&) noexcept = default;
183
184     struct TableInfo {
185         struct VTable;
186
187         StringData name;
188         const VTable* vtable;
189         size_t object_id_index;
190         size_t primary_key_index;
191         DataType primary_key_type = DataType(-1);
192         bool primary_key_nullable = false;
193     };
194
195     mutable std::vector<util::Optional<TableInfo>> m_table_info;
196
197     const TableInfo& get_table_info(const Table&) const;
198     const TableInfo& get_table_info(size_t table_index) const;
199     void clear();
200 };
201
202
203 /// Migrate a server-side Realm file whose history type is
204 /// `Replication::hist_SyncServer` and whose history schema version is 0 (i.e.,
205 /// Realm files without stable identifiers).
206 void import_from_legacy_format(const Group& old_group, Group& new_group, util::Logger&);
207
208 } // namespace sync
209 } // namespace realm
210
211 #endif // REALM_SYNC_OBJECT_HPP
212