added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / table.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 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_TABLE_HPP
20 #define REALM_TABLE_HPP
21
22 #include <algorithm>
23 #include <map>
24 #include <utility>
25 #include <typeinfo>
26 #include <memory>
27 #include <mutex>
28
29 #include <realm/util/features.h>
30 #include <realm/util/thread.hpp>
31 #include <realm/table_ref.hpp>
32 #include <realm/link_view_fwd.hpp>
33 #include <realm/row.hpp>
34 #include <realm/descriptor_fwd.hpp>
35 #include <realm/spec.hpp>
36 #include <realm/mixed.hpp>
37 #include <realm/query.hpp>
38 #include <realm/column.hpp>
39 #include <realm/column_binary.hpp>
40
41 namespace realm {
42
43 class BacklinkColumn;
44 class BinaryColumy;
45 class ConstTableView;
46 class Group;
47 class LinkColumn;
48 class LinkColumnBase;
49 class LinkListColumn;
50 class LinkView;
51 class SortDescriptor;
52 class StringIndex;
53 class TableView;
54 class TableViewBase;
55 class TimestampColumn;
56 template <class>
57 class Columns;
58 template <class>
59 class SubQuery;
60 struct LinkTargetInfo;
61
62 struct SubTable {
63 };
64 struct Link {
65 };
66 typedef Link LinkList;
67 typedef Link BackLink;
68
69 namespace _impl {
70 class TableFriend;
71 }
72 namespace metrics {
73 class QueryInfo;
74 }
75
76 class Replication;
77
78
79 /// FIXME: Table assignment (from any group to any group) could be made aliasing
80 /// safe as follows: Start by cloning source table into target allocator. On
81 /// success, assign, and then deallocate any previous structure at the target.
82 ///
83 /// FIXME: It might be desirable to have a 'table move' feature between two
84 /// places inside the same group (say from a subtable or a mixed column to group
85 /// level). This could be done in a very efficient manner.
86 ///
87 /// FIXME: When compiling in debug mode, all public non-static table functions
88 /// should REALM_ASSERT(is_attached()).
89 class Table {
90 public:
91     /// Construct a new freestanding top-level table with static
92     /// lifetime.
93     ///
94     /// This constructor should be used only when placing a table
95     /// instance on the stack, and it is then the responsibility of
96     /// the application that there are no objects of type TableRef or
97     /// ConstTableRef that refer to it, or to any of its subtables,
98     /// when it goes out of scope. To create a top-level table with
99     /// dynamic lifetime, use Table::create() instead.
100     Table(Allocator& = Allocator::get_default());
101
102     /// Construct a copy of the specified table as a new freestanding
103     /// top-level table with static lifetime.
104     ///
105     /// This constructor should be used only when placing a table
106     /// instance on the stack, and it is then the responsibility of
107     /// the application that there are no objects of type TableRef or
108     /// ConstTableRef that refer to it, or to any of its subtables,
109     /// when it goes out of scope. To create a top-level table with
110     /// dynamic lifetime, use Table::copy() instead.
111     Table(const Table&, Allocator& = Allocator::get_default());
112
113     ~Table() noexcept;
114
115     Allocator& get_alloc() const;
116
117     /// Construct a new freestanding top-level table with dynamic lifetime.
118     static TableRef create(Allocator& = Allocator::get_default());
119
120     /// Construct a copy of the specified table as a new freestanding top-level
121     /// table with dynamic lifetime.
122     TableRef copy(Allocator& = Allocator::get_default()) const;
123
124     /// Returns true if, and only if this accessor is currently attached to an
125     /// underlying table.
126     ///
127     /// A table accessor may get detached from the underlying row for various
128     /// reasons (see below). When it does, it no longer refers to anything, and
129     /// can no longer be used, except for calling is_attached(). The
130     /// consequences of calling other non-static functions on a detached table
131     /// accessor are unspecified. Table accessors obtained by calling functions in
132     /// the Realm API are always in the 'attached' state immediately upon
133     /// return from those functions.
134     ///
135     /// A table accessor of a free-standing table never becomes detached (except
136     /// during its eventual destruction). A group-level table accessor becomes
137     /// detached if the underlying table is removed from the group, or when the
138     /// group accessor is destroyed. A subtable accessor becomes detached if the
139     /// underlying subtable is removed, or if the parent table accessor is
140     /// detached. A table accessor does not become detached for any other reason
141     /// than those mentioned here.
142     ///
143     /// FIXME: High level language bindings will probably want to be able to
144     /// explicitely detach a group and all tables of that group if any modifying
145     /// operation fails (e.g. memory allocation failure) (and something similar
146     /// for freestanding tables) since that leaves the group in state where any
147     /// further access is disallowed. This way they will be able to reliably
148     /// intercept any attempt at accessing such a failed group.
149     ///
150     /// FIXME: The C++ documentation must state that if any modifying operation
151     /// on a group (incl. tables, subtables, and specs) or on a free standing
152     /// table (incl. subtables and specs) fails, then any further access to that
153     /// group (except ~Group()) or freestanding table (except ~Table()) has
154     /// undefined behaviour and is considered an error on behalf of the
155     /// application. Note that even Table::is_attached() is disallowed in this
156     /// case.
157     bool is_attached() const noexcept;
158
159     /// Get the name of this table, if it has one. Only group-level tables have
160     /// names. For a table of any other kind, this function returns the empty
161     /// string.
162     StringData get_name() const noexcept;
163
164     // Whether or not elements can be null.
165     bool is_nullable(size_t col_ndx) const;
166
167     //@{
168     /// Conventience functions for inspecting the dynamic table type.
169     ///
170     /// These functions behave as if they were called on the descriptor returned
171     /// by get_descriptor().
172     size_t get_column_count() const noexcept;
173     DataType get_column_type(size_t column_ndx) const noexcept;
174     StringData get_column_name(size_t column_ndx) const noexcept;
175     size_t get_column_index(StringData name) const noexcept;
176     //@}
177
178     //@{
179     /// Convenience functions for manipulating the dynamic table type.
180     ///
181     /// These function must be called only for tables with independent dynamic
182     /// type. A table has independent dynamic type if the function
183     /// has_shared_type() returns false. A table that is a direct member of a
184     /// group has independent dynamic type. So does a free-standing table, and a
185     /// subtable in a column of type 'mixed'. All other tables have shared
186     /// dynamic type. The consequences of calling any of these functions for a
187     /// table with shared dynamic type are undefined.
188     ///
189     /// Apart from that, these functions behave as if they were called on the
190     /// descriptor returned by get_descriptor(). Note especially that the
191     /// `_link` suffixed functions must be used when inserting link-type
192     /// columns.
193     ///
194     /// If you need to change the shared dynamic type of the subtables in a
195     /// subtable column, consider using the API offered by the Descriptor class.
196     ///
197     /// \sa has_shared_type()
198     /// \sa get_descriptor()
199
200     size_t add_column(DataType type, StringData name, bool nullable = false, DescriptorRef* subdesc = nullptr);
201     void insert_column(size_t column_ndx, DataType type, StringData name, bool nullable = false,
202                        DescriptorRef* subdesc = nullptr);
203
204     // Todo, these prototypes only exist for backwards compatibility. We should remove them because they are error
205     // prone (optional arguments and implicit bool to null-ptr conversion)
206     size_t add_column(DataType type, StringData name, DescriptorRef* subdesc)
207     {
208         return add_column(type, name, false, subdesc);
209     }
210     void insert_column(size_t column_ndx, DataType type, StringData name, DescriptorRef* subdesc)
211     {
212         insert_column(column_ndx, type, name, false, subdesc);
213     }
214
215     size_t add_column_link(DataType type, StringData name, Table& target, LinkType link_type = link_Weak);
216     void insert_column_link(size_t column_ndx, DataType type, StringData name, Table& target,
217                             LinkType link_type = link_Weak);
218     void remove_column(size_t column_ndx);
219     void rename_column(size_t column_ndx, StringData new_name);
220     //@}
221     //@{
222
223     /// has_search_index() returns true if, and only if a search index has been
224     /// added to the specified column. Rather than throwing, it returns false if
225     /// the table accessor is detached or the specified index is out of range.
226     ///
227     /// add_search_index() adds a search index to the specified column of the
228     /// table. It has no effect if a search index has already been added to the
229     /// specified column (idempotency).
230     ///
231     /// remove_search_index() removes the search index from the specified column
232     /// of the table. It has no effect if the specified column has no search
233     /// index. The search index cannot be removed from the primary key of a
234     /// table.
235     ///
236     /// This table must be a root table; that is, it must have an independent
237     /// descriptor. Freestanding tables, group-level tables, and subtables in a
238     /// column of type 'mixed' are all examples of root tables. See add_column()
239     /// for more on this. If you want to manipulate subtable indexes, you must use
240     /// the Descriptor interface.
241     ///
242     /// \param column_ndx The index of a column of the table.
243
244     bool has_search_index(size_t column_ndx) const noexcept;
245     void add_search_index(size_t column_ndx);
246     void remove_search_index(size_t column_ndx);
247
248     //@}
249
250     //@{
251     /// Get the dynamic type descriptor for this table.
252     ///
253     /// Every table has an associated descriptor that specifies its dynamic
254     /// type. For simple tables, that is, tables without subtable columns, the
255     /// dynamic type can be inspected and modified directly using member
256     /// functions such as get_column_count() and add_column(). For more complex
257     /// tables, the type is best managed through the associated descriptor
258     /// object which is returned by this function.
259     ///
260     /// \sa has_shared_type()
261     DescriptorRef get_descriptor();
262     ConstDescriptorRef get_descriptor() const;
263     //@}
264
265     //@{
266     /// Get the dynamic type descriptor for the column with the
267     /// specified index. That column must have type 'table'.
268     ///
269     /// This is merely a shorthand for calling `get_subdescriptor(column_ndx)`
270     /// on the descriptor returned by `get_descriptor()`.
271     DescriptorRef get_subdescriptor(size_t column_ndx);
272     ConstDescriptorRef get_subdescriptor(size_t column_ndx) const;
273     //@}
274
275     //@{
276     /// Get access to an arbitrarily nested dynamic type descriptor.
277     ///
278     /// The returned descriptor is the one you would get by calling
279     /// Descriptor::get_subdescriptor() once for each entry in the specified
280     /// path, starting with the descriptor returned by get_descriptor(). The
281     /// path is allowed to be empty.
282     typedef std::vector<size_t> path_vec;
283     DescriptorRef get_subdescriptor(const path_vec& path);
284     ConstDescriptorRef get_subdescriptor(const path_vec& path) const;
285     //@}
286
287     //@{
288     /// Convenience functions for manipulating nested table types.
289     ///
290     /// These functions behave as if they were called on the descriptor returned
291     /// by `get_subdescriptor(path)`. These function must be called only on
292     /// tables with independent dynamic type.
293     ///
294     /// \return The value returned by add_subcolumn(), is the index of
295     /// the added column within the descriptor referenced by the
296     /// specified path.
297     ///
298     /// \sa Descriptor::add_column()
299     /// \sa has_shared_type()
300     size_t add_subcolumn(const path_vec& path, DataType type, StringData name);
301     void insert_subcolumn(const path_vec& path, size_t column_ndx, DataType type, StringData name);
302     void remove_subcolumn(const path_vec& path, size_t column_ndx);
303     void rename_subcolumn(const path_vec& path, size_t column_ndx, StringData new_name);
304     //@}
305
306     /// Does this table share its type with other tables?
307     ///
308     /// Tables that are direct members of groups have independent
309     /// dynamic types. The same is true for free-standing tables and
310     /// subtables in coulmns of type 'mixed'. For such tables, this
311     /// function returns false.
312     ///
313     /// When a table has a column of type 'table', the cells in that
314     /// column contain subtables. All those subtables have the same
315     /// dynamic type, and they share a single type descriptor. For all
316     /// such subtables, this function returns true. See
317     /// Descriptor::is_root() for more on this.
318     ///
319     /// Please note that Table functions that modify the dynamic type
320     /// directly, such as add_column(), are only allowed to be used on
321     /// tables with non-shared type. If you need to modify a shared
322     /// type, you will have to do that through the descriptor returned
323     /// by get_descriptor(), but note that it will then affect all the
324     /// tables sharing that descriptor.
325     ///
326     /// \sa get_descriptor()
327     /// \sa Descriptor::is_root()
328     bool has_shared_type() const noexcept;
329
330
331     template <class T>
332     Columns<T> column(size_t column); // FIXME: Should this one have been declared noexcept?
333     template <class T>
334     Columns<T> column(const Table& origin, size_t origin_column_ndx);
335
336     template <class T>
337     SubQuery<T> column(size_t column, Query subquery);
338     template <class T>
339     SubQuery<T> column(const Table& origin, size_t origin_column_ndx, Query subquery);
340
341     // Table size and deletion
342     bool is_empty() const noexcept;
343     size_t size() const noexcept;
344
345     typedef BasicRowExpr<Table> RowExpr;
346     typedef BasicRowExpr<const Table> ConstRowExpr;
347
348     RowExpr get(size_t row_ndx) noexcept;
349     ConstRowExpr get(size_t row_ndx) const noexcept;
350
351     RowExpr front() noexcept;
352     ConstRowExpr front() const noexcept;
353
354     RowExpr back() noexcept;
355     ConstRowExpr back() const noexcept;
356
357     RowExpr operator[](size_t row_ndx) noexcept;
358     ConstRowExpr operator[](size_t row_ndx) const noexcept;
359
360
361     //@{
362
363     /// Row handling.
364     ///
365     /// remove() removes the specified row from the table and shifts all rows at
366     /// higher index to fill the vacated slot. This operation assumes that the
367     /// table is ordered, and it is therefore allowed only on tables **without**
368     /// link columns, as link columns are only allowed in unordered tables.
369     ///
370     /// move_last_over() removes the specified row from the table, and if it is
371     /// not the last row in the table, it then moves the last row into the
372     /// vacated slot. This operation assumes that the table is unordered, and it
373     /// may therfore be used on tables with link columns.
374     ///
375     /// remove_recursive() will delete linked rows if the removed link was the
376     /// last one holding on to the row in question. This will be done recursively.
377     ///
378     /// The removal of a row from an unordered table (move_last_over()) may
379     /// cause other linked rows to be cascade-removed. The clearing of a table
380     /// may also cause linked rows to be cascade-removed, but in this respect,
381     /// the effect is exactly as if each row had been removed individually. See
382     /// Descriptor::set_link_type() for details.
383
384     size_t add_empty_row(size_t num_rows = 1);
385     void insert_empty_row(size_t row_ndx, size_t num_rows = 1);
386     size_t add_row_with_key(size_t col_ndx, int64_t key);
387     void remove(size_t row_ndx);
388     void remove_recursive(size_t row_ndx);
389     void remove_last();
390     void move_last_over(size_t row_ndx);
391     void clear();
392     void swap_rows(size_t row_ndx_1, size_t row_ndx_2);
393     void move_row(size_t from_ndx, size_t to_ndx);
394     //@}
395
396     /// Replaces all links to \a row_ndx with links to \a new_row_ndx.
397     ///
398     /// This operation is usually followed by Table::move_last_over()
399     /// as part of Table::set_int_unique() or Table::set_string_unique()
400     /// or Table::set_null_unique() detecting a collision.
401     ///
402     /// \sa Table::move_last_over()
403     /// \sa Table::set_int_unique()
404     /// \sa Table::set_string_unique()
405     /// \sa Table::set_null_unique()
406     void merge_rows(size_t row_ndx, size_t new_row_ndx);
407
408     //@{
409
410     /// Get cell values.
411     /// Will assert if the requested type does not match the column type.
412     ///
413     /// When fetching from a nullable column and the value is null, a default
414     /// value will be returned, except for object like types (StringData,
415     /// BinaryData, Timestamp) which have support for storing nulls. In that
416     /// case, call the `is_null()` method on the returned object to check
417     /// whether the stored value was null. If nullability matters and returning
418     /// a default value is unacceptable, check Table::is_null() before getting a
419     /// cell value.
420     ///
421     /// \sa Table::is_nullable(size_t col_ndx)
422     /// \sa Table::is_null(size_t col_ndx, size_t row_ndx)
423     /// \sa StringData::is_null()
424     int64_t get_int(size_t column_ndx, size_t row_ndx) const noexcept;
425     bool get_bool(size_t column_ndx, size_t row_ndx) const noexcept;
426     OldDateTime get_olddatetime(size_t column_ndx, size_t row_ndx) const noexcept;
427     float get_float(size_t column_ndx, size_t row_ndx) const noexcept;
428     double get_double(size_t column_ndx, size_t row_ndx) const noexcept;
429     StringData get_string(size_t column_ndx, size_t row_ndx) const noexcept;
430     BinaryData get_binary(size_t column_ndx, size_t row_ndx) const noexcept;
431     BinaryIterator get_binary_iterator(size_t column_ndx, size_t row_ndx) const noexcept;
432     Mixed get_mixed(size_t column_ndx, size_t row_ndx) const noexcept;
433     DataType get_mixed_type(size_t column_ndx, size_t row_ndx) const noexcept;
434     Timestamp get_timestamp(size_t column_ndx, size_t row_ndx) const noexcept;
435
436     //@}
437
438     /// Return data from position 'pos' and onwards. If the blob is distributed
439     /// across multiple arrays, you will only get data from one array. 'pos'
440     /// will be updated to be an index to next available data. It will be 0
441     /// if no more data.
442     BinaryData get_binary_at(size_t col_ndx, size_t ndx, size_t& pos) const noexcept;
443
444     template <class T>
445     T get(size_t c, size_t r) const noexcept;
446
447     size_t get_link(size_t column_ndx, size_t row_ndx) const noexcept;
448     bool is_null_link(size_t column_ndx, size_t row_ndx) const noexcept;
449     LinkViewRef get_linklist(size_t column_ndx, size_t row_ndx);
450     ConstLinkViewRef get_linklist(size_t column_ndx, size_t row_ndx) const;
451     size_t get_link_count(size_t column_ndx, size_t row_ndx) const noexcept;
452     bool linklist_is_empty(size_t column_ndx, size_t row_ndx) const noexcept;
453     bool is_null(size_t column_ndx, size_t row_ndx) const noexcept;
454
455     TableRef get_link_target(size_t column_ndx) noexcept;
456     ConstTableRef get_link_target(size_t column_ndx) const noexcept;
457
458     //@{
459
460     /// Set cell values.
461     ///
462     /// It is an error to specify a column index, row index, or string position
463     /// that is out of range.
464     ///
465     /// The number of bytes in a string value must not exceed `max_string_size`,
466     /// and the number of bytes in a binary data value must not exceed
467     /// `max_binary_size`. String must also contain valid UTF-8 encodings. These
468     /// requirements also apply when modifying a string with insert_substring()
469     /// and remove_substring(), and for strings in a mixed columnt. Passing, or
470     /// producing an oversized string or binary data value will cause an
471     /// exception to be thrown.
472     ///
473     /// The "unique" variants (set_int_unique(), set_string_unique(), set_null_unique())
474     /// are intended to be used in the implementation of primary key support. They
475     /// check if the given column already contains one or more values that are
476     /// equal to \a value, and if there are conflicts, it calls
477     /// Table::merge_rows() for the row_ndx to be replaced by the
478     /// existing row, followed by a Table::move_last_over() of row_ndx. The
479     /// return value is always a row index of a row that contains \a value in
480     /// the specified column, possibly different from \a row_ndx if a conflict
481     /// occurred.  Users intending to implement primary keys must therefore
482     /// manually check for duplicates if they want to raise an error instead.
483     ///
484     /// NOTE:  It is an error to call either function after adding elements to a
485     /// linklist in the object. In general, calling set_int_unique() or
486     /// set_string_unique() or set_null_unique() should be the first thing that
487     /// happens after creating a row. These limitations are imposed by limitations
488     /// in the Realm Object Server and may be relaxed in the future. A violation of
489     /// these rules results in a LogicError being thrown.
490     ///
491     /// add_int() adds a 64-bit signed integer to the current value of the
492     /// cell.  If the addition would cause signed integer overflow or
493     /// underflow, the addition "wraps around" with semantics similar to
494     /// unsigned integer arithmetic, such that Table::max_integer + 1 ==
495     /// Table::min_integer and Table::min_integer - 1 == Table::max_integer.
496     /// Note that the wrapping is platform-independent (all platforms wrap in
497     /// the same way regardless of integer representation). If the existing
498     /// value in the cell is null, a LogicError exception is thrown.
499     ///
500     /// insert_substring() inserts the specified string into the currently
501     /// stored string at the specified position. The position must be less than
502     /// or equal to the size of the currently stored string.
503     ///
504     /// remove_substring() removes the specified byte range from the currently
505     /// stored string. The beginning of the range (\a pos) must be less than or
506     /// equal to the size of the currently stored string. If the specified range
507     /// extends beyond the end of the currently stored string, it will be
508     /// silently clamped.
509     ///
510     /// String level modifications performed via insert_substring() and
511     /// remove_substring() are mergable and subject to operational
512     /// transformation. That is, the effect of two causally unrelated
513     /// modifications will in general both be retained during synchronization.
514
515     static const size_t max_string_size = 0xFFFFF8 - Array::header_size - 1;
516     static const size_t max_binary_size = 0xFFFFF8 - Array::header_size;
517
518     // FIXME: These limits should be chosen independently of the underlying
519     // platform's choice to define int64_t and independent of the integer
520     // representation. The current values only work for 2's complement, which is
521     // not guaranteed by the standard.
522     static constexpr int_fast64_t max_integer = std::numeric_limits<int64_t>::max();
523     static constexpr int_fast64_t min_integer = std::numeric_limits<int64_t>::min();
524
525     template <class T>
526     void set(size_t c, size_t r, T value, bool is_default = false);
527
528     template <class T>
529     size_t set_unique(size_t c, size_t r, T value);
530
531     void set_int(size_t column_ndx, size_t row_ndx, int_fast64_t value, bool is_default = false);
532     size_t set_int_unique(size_t column_ndx, size_t row_ndx, int_fast64_t value);
533     void set_bool(size_t column_ndx, size_t row_ndx, bool value, bool is_default = false);
534     void set_olddatetime(size_t column_ndx, size_t row_ndx, OldDateTime value, bool is_default = false);
535     void set_timestamp(size_t column_ndx, size_t row_ndx, Timestamp value, bool is_default = false);
536     template <class E>
537     void set_enum(size_t column_ndx, size_t row_ndx, E value);
538     void set_float(size_t column_ndx, size_t row_ndx, float value, bool is_default = false);
539     void set_double(size_t column_ndx, size_t row_ndx, double value, bool is_default = false);
540     void set_string(size_t column_ndx, size_t row_ndx, StringData value, bool is_default = false);
541     size_t set_string_unique(size_t column_ndx, size_t row_ndx, StringData value);
542     void set_binary(size_t column_ndx, size_t row_ndx, BinaryData value, bool is_default = false);
543     void set_mixed(size_t column_ndx, size_t row_ndx, Mixed value, bool is_default = false);
544     void set_link(size_t column_ndx, size_t row_ndx, size_t target_row_ndx, bool is_default = false);
545     void nullify_link(size_t column_ndx, size_t row_ndx);
546     void set_null(size_t column_ndx, size_t row_ndx, bool is_default = false);
547     void set_null_unique(size_t col_ndx, size_t row_ndx);
548
549     // Sync needs to store blobs bigger than 16 M. This function can be used for that. Data should be read
550     // out again using the get_binary_at() function. Should not be used for user data as normal get_binary()
551     // will just return null if the data is bigger than the limit.
552     void set_binary_big(size_t column_ndx, size_t row_ndx, BinaryData value, bool is_default = false);
553
554     void add_int(size_t column_ndx, size_t row_ndx, int_fast64_t value);
555
556     void insert_substring(size_t col_ndx, size_t row_ndx, size_t pos, StringData);
557     void remove_substring(size_t col_ndx, size_t row_ndx, size_t pos, size_t substring_size = realm::npos);
558
559     //@}
560
561     /// Assumes that the specified column is a subtable column (in
562     /// particular, not a mixed column) and that the specified table
563     /// has a spec that is compatible with that column, that is, the
564     /// number of columns must be the same, and corresponding columns
565     /// must have identical data types (as returned by
566     /// get_column_type()).
567     void set_subtable(size_t col_ndx, size_t row_ndx, const Table*);
568     void set_mixed_subtable(size_t col_ndx, size_t row_ndx, const Table*);
569
570
571     // Sub-tables (works on columns whose type is either 'subtable' or
572     // 'mixed', for a value in a mixed column that is not a subtable,
573     // get_subtable() returns null, get_subtable_size() returns zero,
574     // and clear_subtable() replaces the value with an empty table.)
575     // Currently, subtables of subtables are not supported.
576     TableRef get_subtable(size_t column_ndx, size_t row_ndx);
577     ConstTableRef get_subtable(size_t column_ndx, size_t row_ndx) const;
578     size_t get_subtable_size(size_t column_ndx, size_t row_ndx) const noexcept;
579     void clear_subtable(size_t column_ndx, size_t row_ndx);
580
581     // Backlinks
582     size_t get_backlink_count(size_t row_ndx, bool only_strong_links = false) const noexcept;
583     size_t get_backlink_count(size_t row_ndx, const Table& origin, size_t origin_col_ndx) const noexcept;
584     size_t get_backlink(size_t row_ndx, const Table& origin, size_t origin_col_ndx, size_t backlink_ndx) const
585         noexcept;
586
587
588     //@{
589
590     /// If this accessor is attached to a subtable, then that subtable has a
591     /// parent table, and the subtable either resides in a column of type
592     /// `table` or of type `mixed` in that parent. In that case
593     /// get_parent_table() returns a reference to the accessor associated with
594     /// the parent, and get_parent_row_index() returns the index of the row in
595     /// which the subtable resides. In all other cases (free-standing and
596     /// group-level tables), get_parent_table() returns null and
597     /// get_parent_row_index() returns realm::npos.
598     ///
599     /// If this accessor is attached to a subtable, and \a column_ndx_out is
600     /// specified, then `*column_ndx_out` is set to the index of the column of
601     /// the parent table in which the subtable resides. If this accessor is not
602     /// attached to a subtable, then `*column_ndx_out` will retain its original
603     /// value upon return.
604
605     TableRef get_parent_table(size_t* column_ndx_out = nullptr) noexcept;
606     ConstTableRef get_parent_table(size_t* column_ndx_out = nullptr) const noexcept;
607     size_t get_parent_row_index() const noexcept;
608
609     //@}
610
611
612     /// Only group-level unordered tables can be used as origins or targets of
613     /// links.
614     bool is_group_level() const noexcept;
615
616     /// If this table is a group-level table, then this function returns the
617     /// index of this table within the group. Otherwise it returns realm::npos.
618     size_t get_index_in_group() const noexcept;
619
620     // Aggregate functions
621     size_t count_int(size_t column_ndx, int64_t value) const;
622     size_t count_string(size_t column_ndx, StringData value) const;
623     size_t count_float(size_t column_ndx, float value) const;
624     size_t count_double(size_t column_ndx, double value) const;
625
626     int64_t sum_int(size_t column_ndx) const;
627     double sum_float(size_t column_ndx) const;
628     double sum_double(size_t column_ndx) const;
629     int64_t maximum_int(size_t column_ndx, size_t* return_ndx = nullptr) const;
630     float maximum_float(size_t column_ndx, size_t* return_ndx = nullptr) const;
631     double maximum_double(size_t column_ndx, size_t* return_ndx = nullptr) const;
632     OldDateTime maximum_olddatetime(size_t column_ndx, size_t* return_ndx = nullptr) const;
633     Timestamp maximum_timestamp(size_t column_ndx, size_t* return_ndx = nullptr) const;
634     int64_t minimum_int(size_t column_ndx, size_t* return_ndx = nullptr) const;
635     float minimum_float(size_t column_ndx, size_t* return_ndx = nullptr) const;
636     double minimum_double(size_t column_ndx, size_t* return_ndx = nullptr) const;
637     OldDateTime minimum_olddatetime(size_t column_ndx, size_t* return_ndx = nullptr) const;
638     Timestamp minimum_timestamp(size_t column_ndx, size_t* return_ndx = nullptr) const;
639     double average_int(size_t column_ndx, size_t* value_count = nullptr) const;
640     double average_float(size_t column_ndx, size_t* value_count = nullptr) const;
641     double average_double(size_t column_ndx, size_t* value_count = nullptr) const;
642
643     // Searching
644     template <class T>
645     size_t find_first(size_t column_ndx, T value) const;
646
647     size_t find_first_link(size_t target_row_index) const;
648     size_t find_first_int(size_t column_ndx, int64_t value) const;
649     size_t find_first_bool(size_t column_ndx, bool value) const;
650     size_t find_first_olddatetime(size_t column_ndx, OldDateTime value) const;
651     size_t find_first_timestamp(size_t column_ndx, Timestamp value) const;
652     size_t find_first_float(size_t column_ndx, float value) const;
653     size_t find_first_double(size_t column_ndx, double value) const;
654     size_t find_first_string(size_t column_ndx, StringData value) const;
655     size_t find_first_binary(size_t column_ndx, BinaryData value) const;
656     size_t find_first_null(size_t column_ndx) const;
657
658     TableView find_all_link(size_t target_row_index);
659     ConstTableView find_all_link(size_t target_row_index) const;
660     TableView find_all_int(size_t column_ndx, int64_t value);
661     ConstTableView find_all_int(size_t column_ndx, int64_t value) const;
662     TableView find_all_bool(size_t column_ndx, bool value);
663     ConstTableView find_all_bool(size_t column_ndx, bool value) const;
664     TableView find_all_olddatetime(size_t column_ndx, OldDateTime value);
665     ConstTableView find_all_olddatetime(size_t column_ndx, OldDateTime value) const;
666     TableView find_all_float(size_t column_ndx, float value);
667     ConstTableView find_all_float(size_t column_ndx, float value) const;
668     TableView find_all_double(size_t column_ndx, double value);
669     ConstTableView find_all_double(size_t column_ndx, double value) const;
670     TableView find_all_string(size_t column_ndx, StringData value);
671     ConstTableView find_all_string(size_t column_ndx, StringData value) const;
672     TableView find_all_binary(size_t column_ndx, BinaryData value);
673     ConstTableView find_all_binary(size_t column_ndx, BinaryData value) const;
674     TableView find_all_null(size_t column_ndx);
675     ConstTableView find_all_null(size_t column_ndx) const;
676
677     /// The following column types are supported: String, Integer, OldDateTime, Bool
678     TableView get_distinct_view(size_t column_ndx);
679     ConstTableView get_distinct_view(size_t column_ndx) const;
680
681     TableView get_sorted_view(size_t column_ndx, bool ascending = true);
682     ConstTableView get_sorted_view(size_t column_ndx, bool ascending = true) const;
683
684     TableView get_sorted_view(SortDescriptor order);
685     ConstTableView get_sorted_view(SortDescriptor order) const;
686
687     TableView get_range_view(size_t begin, size_t end);
688     ConstTableView get_range_view(size_t begin, size_t end) const;
689
690     TableView get_backlink_view(size_t row_ndx, Table* src_table, size_t src_col_ndx);
691
692
693     // Pivot / aggregate operation types. Experimental! Please do not document method publicly.
694     enum AggrType {
695         aggr_count,
696         aggr_sum,
697         aggr_avg,
698         aggr_min,
699         aggr_max,
700     };
701
702     // Simple pivot aggregate method. Experimental! Please do not document method publicly.
703     void aggregate(size_t group_by_column, size_t aggr_column, AggrType op, Table& result,
704                    const IntegerColumn* viewrefs = nullptr) const;
705
706     /// Report the current versioning counter for the table. The versioning counter is guaranteed to
707     /// change when the contents of the table changes after advance_read() or promote_to_write(), or
708     /// immediately after calls to methods which change the table. The term "change" means "change of
709     /// value": The storage layout of the table may change, for example due to optimization, but this
710     /// is not considered a change of a value. This means that you *cannot* use a non-changing version
711     /// count to indicate that object addresses (e.g. strings, binary data) remain the same.
712     /// The versioning counter *may* change (but is not required to do so) when another table linked
713     /// from this table, or linking to this table, is changed. The version counter *may* also change
714     /// without any apparent reason.
715     uint_fast64_t get_version_counter() const noexcept;
716
717 private:
718     template <class T>
719     TableView find_all(size_t column_ndx, T value);
720
721 public:
722     //@{
723     /// Find the lower/upper bound according to a column that is
724     /// already sorted in ascending order.
725     ///
726     /// For an integer column at index 0, and an integer value '`v`',
727     /// lower_bound_int(0,v) returns the index '`l`' of the first row
728     /// such that `get_int(0,l) &ge; v`, and upper_bound_int(0,v)
729     /// returns the index '`u`' of the first row such that
730     /// `get_int(0,u) &gt; v`. In both cases, if no such row is found,
731     /// the returned value is the number of rows in the table.
732     ///
733     ///     3 3 3 4 4 4 5 6 7 9 9 9
734     ///     ^     ^     ^     ^     ^
735     ///     |     |     |     |     |
736     ///     |     |     |     |      -- Lower and upper bound of 15
737     ///     |     |     |     |
738     ///     |     |     |      -- Lower and upper bound of 8
739     ///     |     |     |
740     ///     |     |      -- Upper bound of 4
741     ///     |     |
742     ///     |      -- Lower bound of 4
743     ///     |
744     ///      -- Lower and upper bound of 1
745     ///
746     /// These functions are similar to std::lower_bound() and
747     /// std::upper_bound().
748     ///
749     /// The string versions assume that the column is sorted according
750     /// to StringData::operator<().
751     size_t lower_bound_int(size_t column_ndx, int64_t value) const noexcept;
752     size_t upper_bound_int(size_t column_ndx, int64_t value) const noexcept;
753     size_t lower_bound_bool(size_t column_ndx, bool value) const noexcept;
754     size_t upper_bound_bool(size_t column_ndx, bool value) const noexcept;
755     size_t lower_bound_float(size_t column_ndx, float value) const noexcept;
756     size_t upper_bound_float(size_t column_ndx, float value) const noexcept;
757     size_t lower_bound_double(size_t column_ndx, double value) const noexcept;
758     size_t upper_bound_double(size_t column_ndx, double value) const noexcept;
759     size_t lower_bound_string(size_t column_ndx, StringData value) const noexcept;
760     size_t upper_bound_string(size_t column_ndx, StringData value) const noexcept;
761     //@}
762
763     // Queries
764     // Using where(tv) is the new method to perform queries on TableView. The 'tv' can have any order; it does not
765     // need to be sorted, and, resulting view retains its order.
766     Query where(TableViewBase* tv = nullptr)
767     {
768         return Query(*this, tv);
769     }
770
771     // FIXME: We need a ConstQuery class or runtime check against modifications in read transaction.
772     Query where(TableViewBase* tv = nullptr) const
773     {
774         return Query(*this, tv);
775     }
776
777     // Perform queries on a LinkView. The returned Query holds a reference to lv.
778     Query where(const LinkViewRef& lv)
779     {
780         return Query(*this, lv);
781     }
782
783     Table& link(size_t link_column);
784     Table& backlink(const Table& origin, size_t origin_col_ndx);
785
786     // Optimizing. enforce == true will enforce enumeration of all string columns;
787     // enforce == false will auto-evaluate if they should be enumerated or not
788     void optimize(bool enforce = false);
789
790     /// Write this table (or a slice of this table) to the specified
791     /// output stream.
792     ///
793     /// The output will have the same format as any other Realm
794     /// database file, such as those produced by Group::write(). In
795     /// this case, however, the resulting database file will contain
796     /// exactly one table, and that table will contain only the
797     /// specified slice of the source table (this table).
798     ///
799     /// The new table will always have the same dynamic type (see
800     /// Descriptor) as the source table (this table), and unless it is
801     /// overridden (\a override_table_name), the new table will have
802     /// the same name as the source table (see get_name()). Indexes
803     /// (see add_search_index()) will not be carried over to the new
804     /// table.
805     ///
806     /// \param out The destination output stream buffer.
807     ///
808     /// \param offset Index of first row to include (if `slice_size >
809     /// 0`). Must be less than, or equal to size().
810     ///
811     /// \param slice_size Number of rows to include. May be zero. If
812     /// `slice_size > size() - offset`, then the effective size of
813     /// the written slice will be `size() - offset`.
814     ///
815     /// \param override_table_name Custom name to write out instead of
816     /// the actual table name.
817     ///
818     /// \throw std::out_of_range If `offset > size()`.
819     ///
820     /// FIXME: While this function does provided a maximally efficient
821     /// way of serializing part of a table, it offers little in terms
822     /// of general utility. This is unfortunate, because it pulls
823     /// quite a large amount of code into the core library to support
824     /// it.
825     void write(std::ostream& out, size_t offset = 0, size_t slice_size = npos,
826                StringData override_table_name = StringData()) const;
827
828     // Conversion
829     void to_json(std::ostream& out, size_t link_depth = 0,
830                  std::map<std::string, std::string>* renames = nullptr) const;
831     void to_string(std::ostream& out, size_t limit = 500) const;
832     void row_to_string(size_t row_ndx, std::ostream& out) const;
833
834     // Get a reference to this table
835     TableRef get_table_ref()
836     {
837         return TableRef(this);
838     }
839     ConstTableRef get_table_ref() const
840     {
841         return ConstTableRef(this);
842     }
843
844     /// \brief Compare two tables for equality.
845     ///
846     /// Two tables are equal if they have equal descriptors
847     /// (`Descriptor::operator==()`) and equal contents. Equal descriptors imply
848     /// that the two tables have the same columns in the same order. Equal
849     /// contents means that the two tables must have the same number of rows,
850     /// and that for each row index, the two rows must have the same values in
851     /// each column.
852     ///
853     /// In mixed columns, both the value types and the values are required to be
854     /// equal.
855     ///
856     /// For a particular row and column, if the two values are themselves tables
857     /// (subtable and mixed columns) value equality implies a recursive
858     /// invocation of `Table::operator==()`.
859     bool operator==(const Table&) const;
860
861     /// \brief Compare two tables for inequality.
862     ///
863     /// See operator==().
864     bool operator!=(const Table& t) const;
865
866     /// A subtable in a column of type 'table' (which shares descriptor with
867     /// other subtables in the same column) is initially in a degenerate state
868     /// where it takes up a minimal amout of space. This function returns true
869     /// if, and only if the table accessor is attached to such a subtable. This
870     /// function is mainly intended for debugging purposes.
871     bool is_degenerate() const;
872
873     /// Compute the sum of the sizes in number of bytes of all the array nodes
874     /// that currently make up this table. See also
875     /// Group::compute_aggregate_byte_size().
876     ///
877     /// If this table accessor is the detached state, this function returns
878     /// zero.
879     size_t compute_aggregated_byte_size() const noexcept;
880
881     // Debug
882     void verify() const;
883 #ifdef REALM_DEBUG
884     void to_dot(std::ostream&, StringData title = StringData()) const;
885     void print() const;
886     MemStats stats() const;
887     void dump_node_structure() const; // To std::cerr (for GDB)
888     void dump_node_structure(std::ostream&, int level) const;
889 #endif
890
891     class Parent;
892     using HandoverPatch = TableHandoverPatch;
893     static void generate_patch(const Table* ref, std::unique_ptr<HandoverPatch>& patch);
894     static TableRef create_from_and_consume_patch(std::unique_ptr<HandoverPatch>& patch, Group& group);
895
896 protected:
897     /// Get a pointer to the accessor of the specified subtable. The
898     /// accessor will be created if it does not already exist.
899     ///
900     /// The returned table pointer must **always** end up being
901     /// wrapped in some instantiation of BasicTableRef<>.
902     TableRef get_subtable_tableref(size_t col_ndx, size_t row_ndx);
903
904     /// See non-const get_subtable_tableref().
905     ConstTableRef get_subtable_tableref(size_t col_ndx, size_t row_ndx) const;
906
907     /// Compare the rows of two tables under the assumption that the two tables
908     /// have the same number of columns, and the same data type at each column
909     /// index (as expressed through the DataType enum).
910     bool compare_rows(const Table&) const;
911
912     void set_into_mixed(Table* parent, size_t col_ndx, size_t row_ndx) const;
913
914     void check_lists_are_empty(size_t row_ndx) const;
915
916 private:
917     class SliceWriter;
918
919     // Number of rows in this table
920     size_t m_size;
921
922     // Underlying array structure. `m_top` is in use only for root tables; that
923     // is, for tables with independent descriptor. `m_columns` contains a ref
924     // for each column and search index in order of the columns. A search index
925     // ref always occurs immediately after the ref of the column to which the
926     // search index belongs.
927     //
928     // A subtable column (a column of type `type_table`) is essentially just a
929     // column of 'refs' pointing to the root node of each subtable.
930     //
931     // To save space in the database file, a subtable in such a column always
932     // starts out in a degenerate form where nothing is allocated on its behalf,
933     // and a null 'ref' is stored in the corresponding slot of the column. A
934     // subtable remains in this degenerate state until the first row is added to
935     // the subtable.
936     //
937     // For this scheme to work, it must be (and is) possible to create a table
938     // accessor that refers to a degenerate subtable. A table accessor (instance
939     // of `Table`) refers to a degenerate subtable if, and only if `m_columns`
940     // is unattached.
941     //
942     // FIXME: The fact that `m_columns` may be detached means that many
943     // functions (even non-modifying functions) need to check for that before
944     // accessing the contents of the table. This incurs a runtime
945     // overhead. Consider whether this overhead can be eliminated by having
946     // `Table::m_columns` always attached to something, and then detect the
947     // degenerate state in a different way.
948     Array m_top;
949     Array m_columns; // 2nd slot in m_top (for root tables)
950
951     // Management class for the spec object. Only if the table has an independent
952     // spec, the spec object should be deleted when the table object is deleted.
953     // If the table has a shared spec, the spec object is managed by the spec object
954     // of the containing table.
955     class SpecPtr {
956     public:
957         ~SpecPtr()
958          {
959             optionally_delete();
960          }
961         void manage(Spec* ptr)
962         {
963             optionally_delete();
964             m_p = ptr;
965             m_is_managed = true;
966         }
967         void detach()
968         {
969             if (m_is_managed) {
970                 m_p->detach();
971             }
972         }
973         SpecPtr& operator=(Spec* ptr)
974         {
975             optionally_delete();
976             m_p = ptr;
977             m_is_managed = false;
978             return *this;
979         }
980         Spec* operator->() const
981         {
982             return m_p;
983         }
984         Spec* get() const
985         {
986             return m_p;
987         }
988         Spec& operator*() const
989         {
990             return *m_p;
991         }
992         operator bool() const
993         {
994             return m_p != nullptr;
995         }
996         bool is_managed() const
997         {
998             return m_is_managed;
999         }
1000
1001     private:
1002         Spec* m_p = nullptr;
1003         bool m_is_managed = false;
1004
1005         void optionally_delete()
1006         {
1007             if (m_is_managed) {
1008                 delete m_p;
1009             }
1010         }
1011     };
1012
1013     SpecPtr m_spec; // 1st slot in m_top (for root tables)
1014
1015     // Is guaranteed to be empty for a detached accessor. Otherwise it is empty
1016     // when the table accessor is attached to a degenerate subtable (unattached
1017     // `m_columns`), otherwise it contains precisely one column accessor for
1018     // each column in the table, in order.
1019     //
1020     // In some cases an entry may be null. This is currently possible only in
1021     // connection with Group::advance_transact(), but it means that several
1022     // member functions must be prepared to handle these null entries; in
1023     // particular, detach(), ~Table(), functions called on behalf of detach()
1024     // and ~Table(), and functiones called on behalf of
1025     // Group::advance_transact().
1026     typedef std::vector<ColumnBase*> column_accessors;
1027     column_accessors m_cols;
1028
1029     mutable std::atomic<size_t> m_ref_count;
1030
1031     // If this table is a root table (has independent descriptor),
1032     // then Table::m_descriptor refers to the accessor of its
1033     // descriptor when, and only when the descriptor accessor
1034     // exists. This is used to ensure that at most one descriptor
1035     // accessor exists for each underlying descriptor at any given
1036     // point in time. Subdescriptors are kept unique by means of a
1037     // registry in the parent descriptor. Table::m_descriptor is
1038     // always null for tables with shared descriptor.
1039     mutable std::weak_ptr<Descriptor> m_descriptor;
1040
1041     // Table view instances
1042     // Access needs to be protected by m_accessor_mutex
1043     typedef std::vector<TableViewBase*> views;
1044     mutable views m_views;
1045
1046     // Points to first bound row accessor, or is null if there are none.
1047     mutable RowBase* m_row_accessors = nullptr;
1048
1049     // Mutex which must be locked any time the row accessor chain or m_views is used
1050     mutable util::Mutex m_accessor_mutex;
1051
1052     // Used for queries: Items are added with link() method during buildup of query
1053     mutable std::vector<size_t> m_link_chain;
1054
1055     /// Used only in connection with Group::advance_transact() and
1056     /// Table::refresh_accessor_tree().
1057     mutable bool m_mark;
1058
1059     mutable uint_fast64_t m_version;
1060
1061     void erase_row(size_t row_ndx, bool is_move_last_over);
1062     void batch_erase_rows(const IntegerColumn& row_indexes, bool is_move_last_over);
1063     void do_remove(size_t row_ndx, bool broken_reciprocal_backlinks);
1064     void do_move_last_over(size_t row_ndx, bool broken_reciprocal_backlinks);
1065     void do_swap_rows(size_t row_ndx_1, size_t row_ndx_2);
1066     void do_move_row(size_t from_ndx, size_t to_ndx);
1067     void do_merge_rows(size_t row_ndx, size_t new_row_ndx);
1068     void do_clear(bool broken_reciprocal_backlinks);
1069     size_t do_set_link(size_t col_ndx, size_t row_ndx, size_t target_row_ndx);
1070     template <class ColType, class T>
1071     size_t do_find_unique(ColType& col, size_t ndx, T&& value, bool& conflict);
1072     template <class ColType>
1073     size_t do_set_unique_null(ColType& col, size_t ndx, bool& conflict);
1074     template <class ColType, class T>
1075     size_t do_set_unique(ColType& column, size_t row_ndx, T&& value, bool& conflict);
1076
1077     void _add_search_index(size_t column_ndx);
1078     void _remove_search_index(size_t column_ndx);
1079
1080     void rebuild_search_index(size_t current_file_format_version);
1081
1082     // Upgrades OldDateTime columns to Timestamp columns
1083     void upgrade_olddatetime();
1084
1085     // Indicate that the current global state version has been "observed". Until this
1086     // happens, bumping of the global version counter can be bypassed, as any query
1087     // checking for a version change will see the older version change anyways.
1088     // Also returns the table-local version.
1089     uint64_t observe_version() const noexcept;
1090
1091     /// Update the version of this table and all tables which have links to it.
1092     /// This causes all views referring to those tables to go out of sync, so that
1093     /// calls to sync_if_needed() will bring the view up to date by reexecuting the
1094     /// query.
1095     ///
1096     /// \param bump_global chooses whether the global versioning counter must be
1097     /// bumped first as part of the update. This is the normal mode of operation,
1098     /// when a change is made to the table. When calling recursively (following links
1099     /// or going to the parent table), the parameter should be set to false to correctly
1100     /// prune traversal.
1101     void bump_version(bool bump_global = true) const noexcept;
1102
1103     /// Disable copying assignment.
1104     ///
1105     /// It could easily be implemented by calling assign(), but the
1106     /// non-checking nature of the low-level dynamically typed API
1107     /// makes it too risky to offer this feature as an
1108     /// operator.
1109     ///
1110     /// FIXME: assign() has not yet been implemented, but the
1111     /// intention is that it will copy the rows of the argument table
1112     /// into this table after clearing the original contents, and for
1113     /// target tables without a shared spec, it would also copy the
1114     /// spec. For target tables with shared spec, it would be an error
1115     /// to pass an argument table with an incompatible spec, but
1116     /// assign() would not check for spec compatibility. This would
1117     /// make it ideal as a basis for implementing operator=() for
1118     /// typed tables.
1119     Table& operator=(const Table&) = delete;
1120
1121     /// Used when constructing an accessor whose lifetime is going to be managed
1122     /// by reference counting. The lifetime of accessors of free-standing tables
1123     /// allocated on the stack by the application is not managed by reference
1124     /// counting, so that is a case where this tag must **not** be specified.
1125     class ref_count_tag {
1126     };
1127
1128     /// Create an uninitialized accessor whose lifetime is managed by reference
1129     /// counting.
1130     Table(ref_count_tag, Allocator&);
1131
1132     void init(ref_type top_ref, ArrayParent*, size_t ndx_in_parent, bool skip_create_column_accessors = false);
1133     void init(Spec* shared_spec, ArrayParent* parent_column, size_t parent_row_ndx);
1134
1135     static void do_insert_column(Descriptor&, size_t col_ndx, DataType type, StringData name,
1136                                  LinkTargetInfo& link_target_info, bool nullable = false);
1137     static void do_insert_column_unless_exists(Descriptor&, size_t col_ndx, DataType type, StringData name,
1138                                                LinkTargetInfo& link, bool nullable = false,
1139                                                bool* was_inserted = nullptr);
1140     static void do_erase_column(Descriptor&, size_t col_ndx);
1141     static void do_rename_column(Descriptor&, size_t col_ndx, StringData name);
1142
1143     static void do_add_search_index(Descriptor&, size_t col_ndx);
1144     static void do_remove_search_index(Descriptor&, size_t col_ndx);
1145
1146     struct InsertSubtableColumns;
1147     struct EraseSubtableColumns;
1148     struct RenameSubtableColumns;
1149
1150     void insert_root_column(size_t col_ndx, DataType type, StringData name, LinkTargetInfo& link_target,
1151                             bool nullable = false);
1152     void erase_root_column(size_t col_ndx);
1153     void do_insert_root_column(size_t col_ndx, ColumnType, StringData name, bool nullable = false);
1154     void do_erase_root_column(size_t col_ndx);
1155     void do_set_link_type(size_t col_ndx, LinkType);
1156     void insert_backlink_column(size_t origin_table_ndx, size_t origin_col_ndx, size_t backlink_col_ndx);
1157     void erase_backlink_column(size_t origin_table_ndx, size_t origin_col_ndx);
1158     void update_link_target_tables(size_t old_col_ndx_begin, size_t new_col_ndx_begin);
1159     void update_link_target_tables_after_column_move(size_t moved_from, size_t moved_to);
1160
1161     struct SubtableUpdater {
1162         virtual void update(const SubtableColumn&, Array& subcolumns) = 0;
1163         virtual void update_accessor(Table&) = 0;
1164         virtual ~SubtableUpdater()
1165         {
1166         }
1167     };
1168     static void update_subtables(Descriptor&, SubtableUpdater*);
1169     void update_subtables(const size_t* col_path_begin, const size_t* col_path_end, SubtableUpdater*);
1170
1171     struct AccessorUpdater {
1172         virtual void update(Table&) = 0;
1173         virtual void update_parent(Table&) = 0;
1174         virtual ~AccessorUpdater()
1175         {
1176         }
1177     };
1178     void update_accessors(const size_t* col_path_begin, const size_t* col_path_end, AccessorUpdater&);
1179
1180     void create_degen_subtab_columns();
1181     ColumnBase* create_column_accessor(ColumnType, size_t col_ndx, size_t ndx_in_parent);
1182     void destroy_column_accessors() noexcept;
1183
1184     /// Called in the context of Group::commit() to ensure that
1185     /// attached table accessors stay valid across a commit. Please
1186     /// note that this works only for non-transactional commits. Table
1187     /// accessors obtained during a transaction are always detached
1188     /// when the transaction ends.
1189     void update_from_parent(size_t old_baseline) noexcept;
1190
1191     // Support function for conversions
1192     void to_string_header(std::ostream& out, std::vector<size_t>& widths) const;
1193     void to_string_row(size_t row_ndx, std::ostream& out, const std::vector<size_t>& widths) const;
1194
1195     // recursive methods called by to_json, to follow links
1196     void to_json(std::ostream& out, size_t link_depth, std::map<std::string, std::string>& renames,
1197                  std::vector<ref_type>& followed) const;
1198     void to_json_row(size_t row_ndx, std::ostream& out, size_t link_depth,
1199                      std::map<std::string, std::string>& renames, std::vector<ref_type>& followed) const;
1200     void to_json_row(size_t row_ndx, std::ostream& out, size_t link_depth = 0,
1201                      std::map<std::string, std::string>* renames = nullptr) const;
1202
1203     // Detach accessor from underlying table. Caller must ensure that
1204     // a reference count exists upon return, for example by obtaining
1205     // an extra reference count before the call.
1206     //
1207     // This function puts this table accessor into the detached
1208     // state. This detaches it from the underlying structure of array
1209     // nodes. It also recursively detaches accessors for subtables,
1210     // and the type descriptor accessor. When this function returns,
1211     // is_attached() will return false.
1212     //
1213     // This function may be called for a table accessor that is
1214     // already in the detached state (idempotency).
1215     //
1216     // It is also valid to call this function for a table accessor
1217     // that has not yet been detached, but whose underlying structure
1218     // of arrays have changed in an unpredictable/unknown way. This
1219     // kind of change generally happens when a modifying table
1220     // operation fails, and also when one transaction is ended and a
1221     // new one is started.
1222     void detach() noexcept;
1223
1224     /// Detach and remove all attached row, link list, and subtable
1225     /// accessors. This function does not discard the descriptor accessor, if
1226     /// any, and it does not discard column accessors either.
1227     void discard_child_accessors() noexcept;
1228
1229     void discard_row_accessors() noexcept;
1230
1231     // Detach the type descriptor accessor if it exists.
1232     void discard_desc_accessor() noexcept;
1233
1234     void bind_ptr() const noexcept;
1235     void unbind_ptr() const noexcept;
1236
1237     void register_view(const TableViewBase* view);
1238     void unregister_view(const TableViewBase* view) noexcept;
1239     void move_registered_view(const TableViewBase* old_addr, const TableViewBase* new_addr) noexcept;
1240     void discard_views() noexcept;
1241
1242     void register_row_accessor(RowBase*) const noexcept;
1243     void unregister_row_accessor(RowBase*) const noexcept;
1244     void do_unregister_row_accessor(RowBase*) const noexcept;
1245
1246     class UnbindGuard;
1247
1248     ColumnType get_real_column_type(size_t column_ndx) const noexcept;
1249
1250     /// If this table is a group-level table, the parent group is returned,
1251     /// otherwise null is returned.
1252     Group* get_parent_group() const noexcept;
1253
1254     const ColumnBase& get_column_base(size_t column_ndx) const noexcept;
1255     ColumnBase& get_column_base(size_t column_ndx);
1256
1257     const ColumnBaseWithIndex& get_column_base_indexed(size_t ndx) const noexcept;
1258     ColumnBaseWithIndex& get_column_base_indexed(size_t ndx);
1259
1260     template <class T, ColumnType col_type>
1261     T& get_column(size_t ndx);
1262
1263     template <class T, ColumnType col_type>
1264     const T& get_column(size_t ndx) const noexcept;
1265
1266     IntegerColumn& get_column(size_t column_ndx);
1267     const IntegerColumn& get_column(size_t column_ndx) const noexcept;
1268     IntNullColumn& get_column_int_null(size_t column_ndx);
1269     const IntNullColumn& get_column_int_null(size_t column_ndx) const noexcept;
1270     FloatColumn& get_column_float(size_t column_ndx);
1271     const FloatColumn& get_column_float(size_t column_ndx) const noexcept;
1272     DoubleColumn& get_column_double(size_t column_ndx);
1273     const DoubleColumn& get_column_double(size_t column_ndx) const noexcept;
1274     StringColumn& get_column_string(size_t column_ndx);
1275     const StringColumn& get_column_string(size_t column_ndx) const noexcept;
1276     BinaryColumn& get_column_binary(size_t column_ndx);
1277     const BinaryColumn& get_column_binary(size_t column_ndx) const noexcept;
1278     StringEnumColumn& get_column_string_enum(size_t column_ndx);
1279     const StringEnumColumn& get_column_string_enum(size_t column_ndx) const noexcept;
1280     SubtableColumn& get_column_table(size_t column_ndx);
1281     const SubtableColumn& get_column_table(size_t column_ndx) const noexcept;
1282     MixedColumn& get_column_mixed(size_t column_ndx);
1283     const MixedColumn& get_column_mixed(size_t column_ndx) const noexcept;
1284     TimestampColumn& get_column_timestamp(size_t column_ndx);
1285     const TimestampColumn& get_column_timestamp(size_t column_ndx) const noexcept;
1286     const LinkColumnBase& get_column_link_base(size_t ndx) const noexcept;
1287     LinkColumnBase& get_column_link_base(size_t ndx);
1288     const LinkColumn& get_column_link(size_t ndx) const noexcept;
1289     LinkColumn& get_column_link(size_t ndx);
1290     const LinkListColumn& get_column_link_list(size_t ndx) const noexcept;
1291     LinkListColumn& get_column_link_list(size_t ndx);
1292     const BacklinkColumn& get_column_backlink(size_t ndx) const noexcept;
1293     BacklinkColumn& get_column_backlink(size_t ndx);
1294
1295     void verify_column(size_t col_ndx, const ColumnBase* col) const;
1296
1297     void instantiate_before_change();
1298     void validate_column_type(const ColumnBase& col, ColumnType expected_type, size_t ndx) const;
1299
1300     static size_t get_size_from_ref(ref_type top_ref, Allocator&) noexcept;
1301     static size_t get_size_from_ref(ref_type spec_ref, ref_type columns_ref, Allocator&) noexcept;
1302
1303     const Table* get_parent_table_ptr(size_t* column_ndx_out = nullptr) const noexcept;
1304     Table* get_parent_table_ptr(size_t* column_ndx_out = nullptr) noexcept;
1305
1306     /// Create an empty table with independent spec and return just
1307     /// the reference to the underlying memory.
1308     static ref_type create_empty_table(Allocator&);
1309
1310     /// Create a column of the specified type, fill it with the
1311     /// specified number of default values, and return just the
1312     /// reference to the underlying memory.
1313     static ref_type create_column(ColumnType column_type, size_t num_default_values, bool nullable, Allocator&);
1314
1315     /// Construct a copy of the columns array of this table using the
1316     /// specified allocator and return just the ref to that array.
1317     ///
1318     /// In the clone, no string column will be of the enumeration
1319     /// type.
1320     ref_type clone_columns(Allocator&) const;
1321
1322     /// Construct a complete copy of this table (including its spec)
1323     /// using the specified allocator and return just the ref to the
1324     /// new top array.
1325     ref_type clone(Allocator&) const;
1326
1327     /// True for `col_type_Link` and `col_type_LinkList`.
1328     static bool is_link_type(ColumnType) noexcept;
1329
1330     void connect_opposite_link_columns(size_t link_col_ndx, Table& target_table, size_t backlink_col_ndx) noexcept;
1331
1332     //@{
1333
1334     /// Cascading removal of strong links.
1335     ///
1336     /// cascade_break_backlinks_to() removes all backlinks pointing to the row
1337     /// at \a row_ndx. Additionally, if this causes the number of **strong**
1338     /// backlinks originating from a particular opposite row (target row of
1339     /// corresponding forward link) to drop to zero, and that row is not already
1340     /// in \a state.rows, then that row is added to \a state.rows, and
1341     /// cascade_break_backlinks_to() is called recursively for it. This
1342     /// operation is the first half of the cascading row removal operation. The
1343     /// second half is performed by passing the resulting contents of \a
1344     /// state.rows to remove_backlink_broken_rows().
1345     ///
1346     /// Operations that trigger cascading row removal due to explicit removal of
1347     /// one or more rows (the *initiating rows*), should add those rows to \a
1348     /// rows initially, and then call cascade_break_backlinks_to() once for each
1349     /// of them in turn. This is opposed to carrying out the explicit row
1350     /// removals independently, which is also possible, but does require that
1351     /// any initiating rows, that end up in \a state.rows due to link cycles,
1352     /// are removed before passing \a state.rows to
1353     /// remove_backlink_broken_rows(). In the case of clear(), where all rows of
1354     /// a table are explicitly removed, it is better to use
1355     /// cascade_break_backlinks_to_all_rows(), and then carry out the table
1356     /// clearing as an independent step. For operations that trigger cascading
1357     /// row removal for other reasons than explicit row removal, \a state.rows
1358     /// must be empty initially, but cascade_break_backlinks_to() must still be
1359     /// called for each of the initiating rows.
1360     ///
1361     /// When the last non-recursive invocation of cascade_break_backlinks_to()
1362     /// returns, all forward links originating from a row in \a state.rows have
1363     /// had their reciprocal backlinks removed, so remove_backlink_broken_rows()
1364     /// does not perform reciprocal backlink removal at all. Additionally, all
1365     /// remaining backlinks originating from rows in \a state.rows are
1366     /// guaranteed to point to rows that are **not** in \a state.rows. This is
1367     /// true because any backlink that was pointing to a row in \a state.rows
1368     /// has been removed by one of the invocations of
1369     /// cascade_break_backlinks_to(). The set of forward links, that correspond
1370     /// to these remaining backlinks, is precisely the set of forward links that
1371     /// need to be removed/nullified by remove_backlink_broken_rows(), which it
1372     /// does by way of reciprocal forward link removal. Note also, that while
1373     /// all the rows in \a state.rows can have remaining **weak** backlinks
1374     /// originating from them, only the initiating rows in \a state.rows can
1375     /// have remaining **strong** backlinks originating from them. This is true
1376     /// because a non-initiating row is added to \a state.rows only when the
1377     /// last backlink originating from it is lost.
1378     ///
1379     /// Each row removal is replicated individually (as opposed to one
1380     /// replication instruction for the entire cascading operation). This is
1381     /// done because it provides an easy way for Group::advance_transact() to
1382     /// know which tables are affected by the cascade. Note that this has
1383     /// several important consequences: First of all, the replication log
1384     /// receiver must execute the row removal instructions in a non-cascading
1385     /// fashion, meaning that there will be an asymmetry between the two sides
1386     /// in how the effect of the cascade is brought about. While this is fine
1387     /// for simple 1-to-1 replication, it may end up interfering badly with
1388     /// *transaction merging*, when that feature is introduced. Imagine for
1389     /// example that the cascade initiating operation gets canceled during
1390     /// conflict resolution, but some, or all of the induced row removals get to
1391     /// stay. That would break causal consistency. It is important, however, for
1392     /// transaction merging that the cascaded row removals are explicitly
1393     /// mentioned in the replication log, such that they can be used to adjust
1394     /// row indexes during the *operational transform*.
1395     ///
1396     /// cascade_break_backlinks_to_all_rows() has the same affect as calling
1397     /// cascade_break_backlinks_to() once for each row in the table. When
1398     /// calling this function, \a state.stop_on_table must be set to the origin
1399     /// table (origin table of corresponding forward links), and \a
1400     /// state.stop_on_link_list_column must be null.
1401     ///
1402     /// It is immaterial which table remove_backlink_broken_rows() is called on,
1403     /// as long it that table is in the same group as the removed rows.
1404
1405     void cascade_break_backlinks_to(size_t row_ndx, CascadeState& state);
1406     void cascade_break_backlinks_to_all_rows(CascadeState& state);
1407     void remove_backlink_broken_rows(const CascadeState&);
1408
1409     //@}
1410
1411     /// Used by query. Follows chain of link columns and returns final target table
1412     const Table* get_link_chain_target(const std::vector<size_t>& link_chain) const;
1413
1414     /// Remove the specified row by the 'move last over' method.
1415     void do_move_last_over(size_t row_ndx);
1416
1417     // Precondition: 1 <= end - begin
1418     size_t* record_subtable_path(size_t* begin, size_t* end) const noexcept;
1419
1420     /// Check if an accessor exists for the specified subtable. If it does,
1421     /// return a pointer to it, otherwise return null. This function assumes
1422     /// that the specified column index in a valid index into `m_cols` but does
1423     /// not otherwise assume more than minimal accessor consistency (see
1424     /// AccessorConsistencyLevels.)
1425     TableRef get_subtable_accessor(size_t col_ndx, size_t row_ndx) noexcept;
1426
1427     /// Unless the column accessor is missing, this function returns the
1428     /// accessor for the target table of the specified link-type column. The
1429     /// column accessor is said to be missing if `m_cols[col_ndx]` is null, and
1430     /// this can happen only during certain operations such as the updating of
1431     /// the accessor tree when a read transaction is advanced. Note that for
1432     /// link type columns, the target table accessor exists when, and only when
1433     /// the origin table accessor exists. This function assumes that the
1434     /// specified column index in a valid index into `m_cols` and that the
1435     /// column is a link-type column. Beyond that, it assume nothing more than
1436     /// minimal accessor consistency (see AccessorConsistencyLevels.)
1437     Table* get_link_target_table_accessor(size_t col_ndx) noexcept;
1438
1439     void discard_subtable_accessor(size_t col_ndx, size_t row_ndx) noexcept;
1440
1441     void adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept;
1442     void adj_acc_erase_row(size_t row_ndx) noexcept;
1443     void adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept;
1444     void adj_acc_move_row(size_t from_ndx, size_t to_ndx) noexcept;
1445     void adj_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept;
1446
1447     /// Adjust this table accessor and its subordinates after move_last_over()
1448     /// (or its inverse).
1449     ///
1450     /// First, any row, subtable, or link list accessors registered as being at
1451     /// \a to_row_ndx will be detached, as that row is assumed to have been
1452     /// replaced. Next, any row, subtable, or link list accessors registered as
1453     /// being at \a from_row_ndx, will be reregistered as being at \a
1454     /// to_row_ndx, as the row at \a from_row_ndx is assumed to have been moved
1455     /// to \a to_row_ndx.
1456     ///
1457     /// Crucially, if \a to_row_ndx is equal to \a from_row_ndx, then row,
1458     /// subtable, or link list accessors at that row are **still detached**.
1459     ///
1460     /// Additionally, this function causes all link-adjacent tables to be marked
1461     /// (dirty). Two tables are link-adjacent if one is the target table of a
1462     /// link column of the other table. Note that this marking follows these
1463     /// relations in both directions, but only to a depth of one.
1464     ///
1465     /// When this function is used in connection with move_last_over(), set \a
1466     /// to_row_ndx to the index of the row to be removed, and set \a
1467     /// from_row_ndx to the index of the last row in the table. As mentioned
1468     /// earlier, this function can also be used in connection with the **inverse
1469     /// of** move_last_over(), which is an operation that vacates a row by
1470     /// moving its contents into a new last row of the table. In that case, set
1471     /// \a to_row_ndx to one plus the index of the last row in the table, and
1472     /// set \a from_row_ndx to the index of the row to be vacated.
1473     ///
1474     /// This function is used as part of Table::refresh_accessor_tree() to
1475     /// promote the state of the accessors from Minimal Consistency into
1476     /// Structural Correspondence, so it must be able to execute without
1477     /// accessing the underlying array nodes.
1478     void adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept;
1479
1480     void adj_acc_clear_root_table() noexcept;
1481     void adj_acc_clear_nonroot_table() noexcept;
1482     void adj_row_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept;
1483     void adj_row_acc_erase_row(size_t row_ndx) noexcept;
1484     void adj_row_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept;
1485     void adj_row_acc_move_row(size_t from_ndx, size_t to_ndx) noexcept;
1486     void adj_row_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept;
1487
1488     /// Called by adj_acc_move_over() to adjust row accessors.
1489     void adj_row_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept;
1490
1491     void adj_insert_column(size_t col_ndx);
1492     void adj_erase_column(size_t col_ndx) noexcept;
1493
1494     bool is_marked() const noexcept;
1495     void mark() noexcept;
1496     void unmark() noexcept;
1497     void recursive_mark() noexcept;
1498     void mark_link_target_tables(size_t col_ndx_begin) noexcept;
1499     void mark_opposite_link_tables() noexcept;
1500
1501     Replication* get_repl() noexcept;
1502
1503     void set_ndx_in_parent(size_t ndx_in_parent) noexcept;
1504
1505     /// Refresh the part of the accessor tree that is rooted at this
1506     /// table. Subtable accessors will be refreshed only if they are marked
1507     /// (Table::m_mark), and this applies recursively to subtables of
1508     /// subtables. All refreshed table accessors (including this one) will be
1509     /// unmarked upon return.
1510     ///
1511     /// The following conditions are necessary and sufficient for the proper
1512     /// operation of this function:
1513     ///
1514     ///  - This table must be a group-level table, or a subtable. It must not be
1515     ///    a free-standing table (because a free-standing table has no parent).
1516     ///
1517     ///  - The `index in parent` property is correct. The `index in parent`
1518     ///    property of the table is the `index in parent` property of
1519     ///    `m_columns` for subtables with shared descriptor, and the `index in
1520     ///    parent` property of `m_top` for all other tables.
1521     ///
1522     ///  - If this table has shared descriptor, then the `index in parent`
1523     ///    property of the contained spec accessor is correct.
1524     ///
1525     ///  - The parent accessor is in a valid state (already refreshed). If the
1526     ///    parent is a group, then the group accessor (excluding its table
1527     ///    accessors) must be in a valid state. If the parent is a table, then
1528     ///    the table accessor (excluding its subtable accessors) must be in a
1529     ///    valid state.
1530     ///
1531     ///  - Every descendant subtable accessor is marked if it needs to be
1532     ///    refreshed, or if it has a descendant accessor that needs to be
1533     ///    refreshed.
1534     ///
1535     ///  - This table accessor, as well as all its descendant accessors, are in
1536     ///    structural correspondence with the underlying node hierarchy whose
1537     ///    root ref is stored in the parent (see AccessorConsistencyLevels).
1538     void refresh_accessor_tree();
1539
1540     void refresh_spec_accessor();
1541
1542     void refresh_column_accessors(size_t col_ndx_begin = 0);
1543
1544     // Look for link columns starting from col_ndx_begin.
1545     // If a link column is found, follow the link and update it's
1546     // backlink column accessor if it is in different table.
1547     void refresh_link_target_accessors(size_t col_ndx_begin = 0);
1548
1549     bool is_cross_table_link_target() const noexcept;
1550     std::recursive_mutex* get_parent_accessor_management_lock() const;
1551 #ifdef REALM_DEBUG
1552     void to_dot_internal(std::ostream&) const;
1553 #endif
1554
1555     friend class SubtableNode;
1556     friend class _impl::TableFriend;
1557     friend class Query;
1558     friend class metrics::QueryInfo;
1559     template <class>
1560     friend class util::bind_ptr;
1561     template <class>
1562     friend class SimpleQuerySupport;
1563     friend class LangBindHelper;
1564     friend class TableViewBase;
1565     template <class T>
1566     friend class Columns;
1567     friend class Columns<StringData>;
1568     friend class ParentNode;
1569     template <class>
1570     friend class SequentialGetter;
1571     friend class RowBase;
1572     friend class LinksToNode;
1573     friend class LinkMap;
1574     friend class LinkView;
1575     friend class Group;
1576 };
1577
1578 class Table::Parent : public ArrayParent {
1579 public:
1580     ~Parent() noexcept override
1581     {
1582     }
1583
1584 protected:
1585     virtual StringData get_child_name(size_t child_ndx) const noexcept;
1586
1587     /// If children are group-level tables, then this function returns the
1588     /// group. Otherwise it returns null.
1589     virtual Group* get_parent_group() noexcept;
1590
1591     /// If children are subtables, then this function returns the
1592     /// parent table. Otherwise it returns null.
1593     ///
1594     /// If \a column_ndx_out is not null, this function must assign the index of
1595     /// the column within the parent table to `*column_ndx_out` when , and only
1596     /// when this table parent is a column in a parent table.
1597     virtual Table* get_parent_table(size_t* column_ndx_out = nullptr) noexcept;
1598
1599     virtual Spec* get_subtable_spec() noexcept;
1600
1601     /// Must be called whenever a child table accessor is about to be destroyed.
1602     ///
1603     /// Note that the argument is a pointer to the child Table rather than its
1604     /// `ndx_in_parent` property. This is because only minimal accessor
1605     /// consistency can be assumed by this function.
1606     virtual void child_accessor_destroyed(Table* child) noexcept = 0;
1607
1608
1609     virtual size_t* record_subtable_path(size_t* begin, size_t* end) noexcept;
1610     virtual std::recursive_mutex* get_accessor_management_lock() noexcept = 0;
1611
1612     friend class Table;
1613 };
1614
1615
1616 // Implementation:
1617
1618
1619 inline uint_fast64_t Table::get_version_counter() const noexcept
1620 {
1621     return observe_version();
1622 }
1623
1624 inline uint64_t Table::observe_version() const noexcept
1625 {
1626     m_top.get_alloc().observe_version();
1627     return m_version;
1628 }
1629
1630 inline void Table::bump_version(bool bump_global) const noexcept
1631 {
1632     if (bump_global) {
1633         // This is only set on initial entry through an operation on the same
1634         // table.  recursive calls (via parent or via backlinks) must be done
1635         // with bump_global=false.
1636         m_top.get_alloc().bump_global_version();
1637     }
1638     if (m_top.get_alloc().should_propagate_version(m_version)) {
1639         if (const Table* parent = get_parent_table_ptr())
1640             parent->bump_version(false);
1641         // Recurse through linked tables, use m_mark to avoid infinite recursion
1642         for (auto& column_ptr : m_cols) {
1643             // We may meet a null pointer in place of a backlink column, pending
1644             // replacement with a new one. This can happen ONLY when creation of
1645             // the corresponding forward link column in the origin table is
1646             // pending as well. In this case it is ok to just ignore the zeroed
1647             // backlink column, because the origin table is guaranteed to also
1648             // be refreshed/marked dirty and hence have it's version bumped.
1649             if (column_ptr != nullptr)
1650                 column_ptr->bump_link_origin_table_version();
1651         }
1652     }
1653 }
1654
1655 inline void Table::remove(size_t row_ndx)
1656 {
1657     bool is_move_last_over = false;
1658     erase_row(row_ndx, is_move_last_over); // Throws
1659 }
1660
1661 inline void Table::move_last_over(size_t row_ndx)
1662 {
1663     bool is_move_last_over = true;
1664     erase_row(row_ndx, is_move_last_over); // Throws
1665 }
1666
1667 inline void Table::remove_last()
1668 {
1669     if (!is_empty())
1670         remove(size() - 1);
1671 }
1672
1673 // A good place to start if you want to understand the memory ordering
1674 // chosen for the operations below is http://preshing.com/20130922/acquire-and-release-fences/
1675 inline void Table::bind_ptr() const noexcept
1676 {
1677     m_ref_count.fetch_add(1, std::memory_order_relaxed);
1678 }
1679
1680 inline void Table::unbind_ptr() const noexcept
1681 {
1682     // The delete operation runs the destructor, and the destructor
1683     // must always see all changes to the object being deleted.
1684     // Within each thread, we know that unbind_ptr will always happen after
1685     // any changes, so it is a convenient place to do a release.
1686     // The release will then be observed by the acquire fence in
1687     // the case where delete is actually called (the count reaches 0)
1688     if (m_ref_count.fetch_sub(1, std::memory_order_release) != 1) {
1689         return;
1690     }
1691
1692     std::atomic_thread_fence(std::memory_order_acquire);
1693
1694     std::recursive_mutex* lock = get_parent_accessor_management_lock();
1695     if (lock) {
1696         std::lock_guard<std::recursive_mutex> lg(*lock);
1697         if (m_ref_count == 0)
1698             delete this;
1699     }
1700     else {
1701         delete this;
1702     }
1703 }
1704
1705 inline void Table::register_view(const TableViewBase* view)
1706 {
1707     util::LockGuard lock(m_accessor_mutex);
1708     // Casting away constness here - operations done on tableviews
1709     // through m_views are all internal and preserving "some" kind
1710     // of logical constness.
1711     m_views.push_back(const_cast<TableViewBase*>(view));
1712 }
1713
1714 inline bool Table::is_attached() const noexcept
1715 {
1716     // Note that it is not possible to tie the state of attachment of a table to
1717     // the state of attachment of m_top, because tables with shared spec do not
1718     // have a 'top' array. Neither is it possible to tie it to the state of
1719     // attachment of m_columns, because subtables with shared spec start out in
1720     // a degenerate form where they do not have a 'columns' array. For these
1721     // reasons, it is neccessary to define the notion of attachment for a table
1722     // as follows: A table is attached if, and ony if m_column stores a non-null
1723     // parent pointer. This works because even for degenerate subtables,
1724     // m_columns is initialized with the correct parent pointer.
1725     return m_columns.has_parent();
1726 }
1727
1728 inline StringData Table::get_name() const noexcept
1729 {
1730     REALM_ASSERT(is_attached());
1731     const Array& real_top = m_top.is_attached() ? m_top : m_columns;
1732     ArrayParent* parent = real_top.get_parent();
1733     if (!parent)
1734         return StringData("");
1735     size_t index_in_parent = real_top.get_ndx_in_parent();
1736     REALM_ASSERT(dynamic_cast<Parent*>(parent));
1737     return static_cast<Parent*>(parent)->get_child_name(index_in_parent);
1738 }
1739
1740 inline size_t Table::get_column_count() const noexcept
1741 {
1742     REALM_ASSERT(is_attached());
1743     return m_spec->get_public_column_count();
1744 }
1745
1746 inline StringData Table::get_column_name(size_t ndx) const noexcept
1747 {
1748     REALM_ASSERT_3(ndx, <, get_column_count());
1749     return m_spec->get_column_name(ndx);
1750 }
1751
1752 inline size_t Table::get_column_index(StringData name) const noexcept
1753 {
1754     REALM_ASSERT(is_attached());
1755     return m_spec->get_column_index(name);
1756 }
1757
1758 inline ColumnType Table::get_real_column_type(size_t ndx) const noexcept
1759 {
1760     REALM_ASSERT_3(ndx, <, m_spec->get_column_count());
1761     return m_spec->get_column_type(ndx);
1762 }
1763
1764 inline DataType Table::get_column_type(size_t ndx) const noexcept
1765 {
1766     REALM_ASSERT_3(ndx, <, m_spec->get_column_count());
1767     return m_spec->get_public_column_type(ndx);
1768 }
1769
1770 template <class Col, ColumnType col_type>
1771 inline Col& Table::get_column(size_t ndx)
1772 {
1773     ColumnBase& col = get_column_base(ndx);
1774 #ifdef REALM_DEBUG
1775     validate_column_type(col, col_type, ndx);
1776 #endif
1777     REALM_ASSERT(typeid(Col) == typeid(col));
1778     return static_cast<Col&>(col);
1779 }
1780
1781 template <class Col, ColumnType col_type>
1782 inline const Col& Table::get_column(size_t ndx) const noexcept
1783 {
1784     const ColumnBase& col = get_column_base(ndx);
1785 #ifdef REALM_DEBUG
1786     validate_column_type(col, col_type, ndx);
1787 #endif
1788     REALM_ASSERT(typeid(Col) == typeid(col));
1789     return static_cast<const Col&>(col);
1790 }
1791
1792 inline bool Table::has_shared_type() const noexcept
1793 {
1794     REALM_ASSERT(is_attached());
1795     return !m_top.is_attached();
1796 }
1797
1798 inline void Table::verify_column(size_t col_ndx, const ColumnBase* col) const
1799 {
1800     // Check if the column exists at the expected location
1801     if (REALM_LIKELY(col_ndx < m_cols.size() && m_cols[col_ndx] == col))
1802         return;
1803     // The column might be elsewhere in the list
1804     for (auto c : m_cols) {
1805         if (c == col)
1806             return;
1807     }
1808     throw LogicError(LogicError::column_does_not_exist);
1809 }
1810
1811 class Table::UnbindGuard {
1812 public:
1813     UnbindGuard(Table* table) noexcept
1814         : m_table(table)
1815     {
1816     }
1817
1818     ~UnbindGuard() noexcept
1819     {
1820         if (m_table)
1821             m_table->unbind_ptr();
1822     }
1823
1824     Table& operator*() const noexcept
1825     {
1826         return *m_table;
1827     }
1828
1829     Table* operator->() const noexcept
1830     {
1831         return m_table;
1832     }
1833
1834     Table* get() const noexcept
1835     {
1836         return m_table;
1837     }
1838
1839     Table* release() noexcept
1840     {
1841         Table* table = m_table;
1842         m_table = nullptr;
1843         return table;
1844     }
1845
1846 private:
1847     Table* m_table;
1848 };
1849
1850
1851 inline Table::Table(Allocator& alloc)
1852     : m_top(alloc)
1853     , m_columns(alloc)
1854 {
1855     m_ref_count = 1; // Explicitly managed lifetime
1856
1857     ref_type ref = create_empty_table(alloc); // Throws
1858     Parent* parent = nullptr;
1859     size_t ndx_in_parent = 0;
1860     init(ref, parent, ndx_in_parent);
1861 }
1862
1863 inline Table::Table(const Table& t, Allocator& alloc)
1864     : m_top(alloc)
1865     , m_columns(alloc)
1866 {
1867     m_ref_count = 1; // Explicitly managed lifetime
1868
1869     ref_type ref = t.clone(alloc); // Throws
1870     Parent* parent = nullptr;
1871     size_t ndx_in_parent = 0;
1872     init(ref, parent, ndx_in_parent);
1873 }
1874
1875 inline Table::Table(ref_count_tag, Allocator& alloc)
1876     : m_top(alloc)
1877     , m_columns(alloc)
1878 {
1879     m_ref_count = 0; // Lifetime managed by reference counting
1880 }
1881
1882 inline Allocator& Table::get_alloc() const
1883 {
1884     return m_top.get_alloc();
1885 }
1886
1887 inline TableRef Table::create(Allocator& alloc)
1888 {
1889     std::unique_ptr<Table> table(new Table(ref_count_tag(), alloc)); // Throws
1890     ref_type ref = create_empty_table(alloc);                        // Throws
1891     Parent* parent = nullptr;
1892     size_t ndx_in_parent = 0;
1893     table->init(ref, parent, ndx_in_parent); // Throws
1894     return table.release()->get_table_ref();
1895 }
1896
1897 inline TableRef Table::copy(Allocator& alloc) const
1898 {
1899     std::unique_ptr<Table> table(new Table(ref_count_tag(), alloc)); // Throws
1900     ref_type ref = clone(alloc);                                     // Throws
1901     Parent* parent = nullptr;
1902     size_t ndx_in_parent = 0;
1903     table->init(ref, parent, ndx_in_parent); // Throws
1904     return table.release()->get_table_ref();
1905 }
1906
1907 // For use by queries
1908 template <class T>
1909 inline Columns<T> Table::column(size_t column_ndx)
1910 {
1911     std::vector<size_t> link_chain = std::move(m_link_chain);
1912     m_link_chain.clear();
1913
1914     // Check if user-given template type equals Realm type. Todo, we should clean up and reuse all our
1915     // type traits (all the is_same() cases below).
1916     const Table* table = get_link_chain_target(link_chain);
1917
1918     realm::DataType ct = table->get_column_type(column_ndx);
1919     if (std::is_same<T, int64_t>::value && ct != type_Int)
1920         throw(LogicError::type_mismatch);
1921     else if (std::is_same<T, bool>::value && ct != type_Bool)
1922         throw(LogicError::type_mismatch);
1923     else if (std::is_same<T, realm::OldDateTime>::value && ct != type_OldDateTime)
1924         throw(LogicError::type_mismatch);
1925     else if (std::is_same<T, float>::value && ct != type_Float)
1926         throw(LogicError::type_mismatch);
1927     else if (std::is_same<T, double>::value && ct != type_Double)
1928         throw(LogicError::type_mismatch);
1929
1930     if (std::is_same<T, Link>::value || std::is_same<T, LinkList>::value || std::is_same<T, BackLink>::value) {
1931         link_chain.push_back(column_ndx);
1932     }
1933
1934     return Columns<T>(column_ndx, this, std::move(link_chain));
1935 }
1936
1937 template <class T>
1938 inline Columns<T> Table::column(const Table& origin, size_t origin_col_ndx)
1939 {
1940     static_assert(std::is_same<T, BackLink>::value, "");
1941
1942     size_t origin_table_ndx = origin.get_index_in_group();
1943     const Table& current_target_table = *get_link_chain_target(m_link_chain);
1944     size_t backlink_col_ndx = current_target_table.m_spec->find_backlink_column(origin_table_ndx, origin_col_ndx);
1945
1946     std::vector<size_t> link_chain = std::move(m_link_chain);
1947     m_link_chain.clear();
1948     link_chain.push_back(backlink_col_ndx);
1949
1950     return Columns<T>(backlink_col_ndx, this, std::move(link_chain));
1951 }
1952
1953 template <class T>
1954 SubQuery<T> Table::column(size_t column_ndx, Query subquery)
1955 {
1956     static_assert(std::is_same<T, LinkList>::value, "A subquery must involve a link list or backlink column");
1957     return SubQuery<T>(column<T>(column_ndx), std::move(subquery));
1958 }
1959
1960 template <class T>
1961 SubQuery<T> Table::column(const Table& origin, size_t origin_col_ndx, Query subquery)
1962 {
1963     static_assert(std::is_same<T, BackLink>::value, "A subquery must involve a link list or backlink column");
1964     return SubQuery<T>(column<T>(origin, origin_col_ndx), std::move(subquery));
1965 }
1966
1967 // For use by queries
1968 inline Table& Table::link(size_t link_column)
1969 {
1970     m_link_chain.push_back(link_column);
1971     return *this;
1972 }
1973
1974 inline Table& Table::backlink(const Table& origin, size_t origin_col_ndx)
1975 {
1976     size_t origin_table_ndx = origin.get_index_in_group();
1977     const Table& current_target_table = *get_link_chain_target(m_link_chain);
1978     size_t backlink_col_ndx = current_target_table.m_spec->find_backlink_column(origin_table_ndx, origin_col_ndx);
1979     return link(backlink_col_ndx);
1980 }
1981
1982 inline bool Table::is_empty() const noexcept
1983 {
1984     return m_size == 0;
1985 }
1986
1987 inline size_t Table::size() const noexcept
1988 {
1989     return m_size;
1990 }
1991
1992 inline Table::RowExpr Table::get(size_t row_ndx) noexcept
1993 {
1994     REALM_ASSERT_3(row_ndx, <, size());
1995     return RowExpr(this, row_ndx);
1996 }
1997
1998 inline Table::ConstRowExpr Table::get(size_t row_ndx) const noexcept
1999 {
2000     REALM_ASSERT_3(row_ndx, <, size());
2001     return ConstRowExpr(this, row_ndx);
2002 }
2003
2004 inline Table::RowExpr Table::front() noexcept
2005 {
2006     return get(0);
2007 }
2008
2009 inline Table::ConstRowExpr Table::front() const noexcept
2010 {
2011     return get(0);
2012 }
2013
2014 inline Table::RowExpr Table::back() noexcept
2015 {
2016     return get(m_size - 1);
2017 }
2018
2019 inline Table::ConstRowExpr Table::back() const noexcept
2020 {
2021     return get(m_size - 1);
2022 }
2023
2024 inline Table::RowExpr Table::operator[](size_t row_ndx) noexcept
2025 {
2026     return get(row_ndx);
2027 }
2028
2029 inline Table::ConstRowExpr Table::operator[](size_t row_ndx) const noexcept
2030 {
2031     return get(row_ndx);
2032 }
2033
2034 inline size_t Table::add_empty_row(size_t num_rows)
2035 {
2036     size_t row_ndx = m_size;
2037     insert_empty_row(row_ndx, num_rows); // Throws
2038     return row_ndx;                      // Return index of first new row
2039 }
2040
2041 inline ConstTableRef Table::get_subtable_tableref(size_t col_ndx, size_t row_ndx) const
2042 {
2043     return const_cast<Table*>(this)->get_subtable_tableref(col_ndx, row_ndx); // Throws
2044 }
2045
2046 inline bool Table::is_null_link(size_t col_ndx, size_t row_ndx) const noexcept
2047 {
2048     return get_link(col_ndx, row_ndx) == realm::npos;
2049 }
2050
2051 inline ConstTableRef Table::get_link_target(size_t col_ndx) const noexcept
2052 {
2053     return const_cast<Table*>(this)->get_link_target(col_ndx);
2054 }
2055
2056 template <class E>
2057 inline void Table::set_enum(size_t column_ndx, size_t row_ndx, E value)
2058 {
2059     set_int(column_ndx, row_ndx, value);
2060 }
2061
2062 inline void Table::nullify_link(size_t col_ndx, size_t row_ndx)
2063 {
2064     set_link(col_ndx, row_ndx, realm::npos);
2065 }
2066
2067 inline TableRef Table::get_subtable(size_t column_ndx, size_t row_ndx)
2068 {
2069     return get_subtable_tableref(column_ndx, row_ndx);
2070 }
2071
2072 inline ConstTableRef Table::get_subtable(size_t column_ndx, size_t row_ndx) const
2073 {
2074     return get_subtable_tableref(column_ndx, row_ndx);
2075 }
2076
2077 inline ConstTableRef Table::get_parent_table(size_t* column_ndx_out) const noexcept
2078 {
2079     return ConstTableRef(get_parent_table_ptr(column_ndx_out));
2080 }
2081
2082 inline TableRef Table::get_parent_table(size_t* column_ndx_out) noexcept
2083 {
2084     return TableRef(get_parent_table_ptr(column_ndx_out));
2085 }
2086
2087 inline bool Table::is_group_level() const noexcept
2088 {
2089     return bool(get_parent_group());
2090 }
2091
2092 inline bool Table::operator==(const Table& t) const
2093 {
2094     return *m_spec == *t.m_spec && compare_rows(t); // Throws
2095 }
2096
2097 inline bool Table::operator!=(const Table& t) const
2098 {
2099     return !(*this == t); // Throws
2100 }
2101
2102 inline bool Table::is_degenerate() const
2103 {
2104     if (!is_attached()) {
2105         throw LogicError{LogicError::detached_accessor};
2106     }
2107
2108     return !m_columns.is_attached();
2109 }
2110
2111 inline void Table::set_into_mixed(Table* parent, size_t col_ndx, size_t row_ndx) const
2112 {
2113     parent->set_mixed_subtable(col_ndx, row_ndx, this);
2114 }
2115
2116 inline size_t Table::get_size_from_ref(ref_type top_ref, Allocator& alloc) noexcept
2117 {
2118     const char* top_header = alloc.translate(top_ref);
2119     std::pair<int_least64_t, int_least64_t> p = Array::get_two(top_header, 0);
2120     ref_type spec_ref = to_ref(p.first), columns_ref = to_ref(p.second);
2121     return get_size_from_ref(spec_ref, columns_ref, alloc);
2122 }
2123
2124 inline Table* Table::get_parent_table_ptr(size_t* column_ndx_out) noexcept
2125 {
2126     const Table* parent = const_cast<const Table*>(this)->get_parent_table_ptr(column_ndx_out);
2127     return const_cast<Table*>(parent);
2128 }
2129
2130 inline bool Table::is_link_type(ColumnType col_type) noexcept
2131 {
2132     return col_type == col_type_Link || col_type == col_type_LinkList;
2133 }
2134
2135 inline size_t* Table::record_subtable_path(size_t* begin, size_t* end) const noexcept
2136 {
2137     const Array& real_top = m_top.is_attached() ? m_top : m_columns;
2138     size_t index_in_parent = real_top.get_ndx_in_parent();
2139     REALM_ASSERT_3(begin, <, end);
2140     *begin++ = index_in_parent;
2141     ArrayParent* parent = real_top.get_parent();
2142     REALM_ASSERT(parent);
2143     REALM_ASSERT(dynamic_cast<Parent*>(parent));
2144     return static_cast<Parent*>(parent)->record_subtable_path(begin, end);
2145 }
2146
2147 inline size_t* Table::Parent::record_subtable_path(size_t* begin, size_t*) noexcept
2148 {
2149     return begin;
2150 }
2151
2152 inline bool Table::is_marked() const noexcept
2153 {
2154     return m_mark;
2155 }
2156
2157 inline void Table::mark() noexcept
2158 {
2159     m_mark = true;
2160 }
2161
2162 inline void Table::unmark() noexcept
2163 {
2164     m_mark = false;
2165 }
2166
2167 inline Replication* Table::get_repl() noexcept
2168 {
2169     return m_top.get_alloc().get_replication();
2170 }
2171
2172 inline void Table::set_ndx_in_parent(size_t ndx_in_parent) noexcept
2173 {
2174     if (m_top.is_attached()) {
2175         // Root table (independent descriptor)
2176         m_top.set_ndx_in_parent(ndx_in_parent);
2177     }
2178     else {
2179         // Subtable with shared descriptor
2180         m_columns.set_ndx_in_parent(ndx_in_parent);
2181     }
2182 }
2183
2184 // Declare our explicit specializations so that the inline wrappers don't try
2185 // to instantiate them
2186 template<> int64_t Table::get<int64_t>(size_t, size_t) const noexcept;
2187 template<> util::Optional<int64_t> Table::get<util::Optional<int64_t>>(size_t, size_t) const noexcept;
2188 template<> bool Table::get<bool>(size_t, size_t) const noexcept;
2189 template<> Optional<bool> Table::get<Optional<bool>>(size_t, size_t) const noexcept;
2190 template<> float Table::get<float>(size_t, size_t) const noexcept;
2191 template<> util::Optional<float> Table::get<util::Optional<float>>(size_t, size_t) const noexcept;
2192 template<> double Table::get<double>(size_t, size_t) const noexcept;
2193 template<> util::Optional<double> Table::get<util::Optional<double>>(size_t, size_t) const noexcept;
2194 template<> OldDateTime Table::get<OldDateTime>(size_t, size_t) const noexcept;
2195 template<> Timestamp Table::get<Timestamp>(size_t, size_t) const noexcept;
2196 template<> StringData Table::get<StringData>(size_t, size_t) const noexcept;
2197 template<> BinaryData Table::get<BinaryData>(size_t, size_t) const noexcept;
2198 template<> BinaryIterator Table::get<BinaryIterator>(size_t, size_t) const noexcept;
2199 template<> Mixed Table::get<Mixed>(size_t, size_t) const noexcept;
2200
2201 template<> void Table::set<int64_t>(size_t, size_t, int64_t, bool);
2202 template<> void Table::set<bool>(size_t, size_t, bool, bool);
2203 template<> void Table::set<float>(size_t, size_t, float, bool);
2204 template<> void Table::set<double>(size_t, size_t, double, bool);
2205 template<> void Table::set<OldDateTime>(size_t, size_t, OldDateTime, bool);
2206 template<> void Table::set<Timestamp>(size_t, size_t, Timestamp, bool);
2207 template<> void Table::set<StringData>(size_t, size_t, StringData, bool);
2208 template<> void Table::set<BinaryData>(size_t, size_t, BinaryData, bool);
2209 template<> void Table::set<Mixed>(size_t, size_t, Mixed, bool);
2210 template<> void Table::set<null>(size_t, size_t, null, bool);
2211
2212 template<> size_t Table::set_unique<int64_t>(size_t, size_t, int64_t);
2213 template<> size_t Table::set_unique<StringData>(size_t, size_t, StringData);
2214 template<> size_t Table::set_unique<null>(size_t, size_t, null);
2215
2216
2217 inline int64_t Table::get_int(size_t col_ndx, size_t ndx) const noexcept
2218 {
2219     if (is_nullable(col_ndx))
2220         return get<util::Optional<int64_t>>(col_ndx, ndx).value_or(0);
2221     else
2222         return get<int64_t>(col_ndx, ndx);
2223 }
2224
2225 inline size_t Table::set_int_unique(size_t col_ndx, size_t ndx, int_fast64_t value)
2226 {
2227     return set_unique(col_ndx, ndx, value);
2228 }
2229
2230 inline void Table::set_int(size_t col_ndx, size_t ndx, int_fast64_t value, bool is_default)
2231 {
2232     return set(col_ndx, ndx, value, is_default);
2233 }
2234
2235 inline Timestamp Table::get_timestamp(size_t col_ndx, size_t ndx) const noexcept
2236 {
2237     return get<Timestamp>(col_ndx, ndx);
2238 }
2239
2240 inline void Table::set_timestamp(size_t col_ndx, size_t ndx, Timestamp value, bool is_default)
2241 {
2242     return set(col_ndx, ndx, value, is_default);
2243 }
2244
2245 inline bool Table::get_bool(size_t col_ndx, size_t ndx) const noexcept
2246 {
2247     if (is_nullable(col_ndx))
2248         return get<util::Optional<bool>>(col_ndx, ndx).value_or(false);
2249     else
2250         return get<bool>(col_ndx, ndx);
2251 }
2252
2253 inline void Table::set_bool(size_t col_ndx, size_t ndx, bool value, bool is_default)
2254 {
2255     return set(col_ndx, ndx, value, is_default);
2256 }
2257
2258 inline OldDateTime Table::get_olddatetime(size_t col_ndx, size_t ndx) const noexcept
2259 {
2260     return get<OldDateTime>(col_ndx, ndx);
2261 }
2262
2263 inline void Table::set_olddatetime(size_t col_ndx, size_t ndx, OldDateTime value, bool is_default)
2264 {
2265     return set(col_ndx, ndx, value, is_default);
2266 }
2267
2268 inline float Table::get_float(size_t col_ndx, size_t ndx) const noexcept
2269 {
2270     float f = get<float>(col_ndx, ndx);
2271     return null::is_null_float(f) ? 0.0f : f;
2272 }
2273
2274 inline void Table::set_float(size_t col_ndx, size_t ndx, float value, bool is_default)
2275 {
2276     return set(col_ndx, ndx, value, is_default);
2277 }
2278
2279 inline double Table::get_double(size_t col_ndx, size_t ndx) const noexcept
2280 {
2281     double d = get<double>(col_ndx, ndx);
2282     return null::is_null_float(d) ? 0.0 : d;
2283 }
2284
2285 inline void Table::set_double(size_t col_ndx, size_t ndx, double value, bool is_default)
2286 {
2287     return set(col_ndx, ndx, value, is_default);
2288 }
2289
2290 inline StringData Table::get_string(size_t col_ndx, size_t ndx) const noexcept
2291 {
2292     return get<StringData>(col_ndx, ndx);
2293 }
2294
2295 inline void Table::set_string(size_t col_ndx, size_t ndx, StringData value, bool is_default)
2296 {
2297     return set(col_ndx, ndx, value, is_default);
2298 }
2299
2300 inline size_t Table::set_string_unique(size_t col_ndx, size_t ndx, StringData value)
2301 {
2302     return set_unique(col_ndx, ndx, value);
2303 }
2304
2305 inline BinaryData Table::get_binary(size_t col_ndx, size_t ndx) const noexcept
2306 {
2307     return get<BinaryData>(col_ndx, ndx);
2308 }
2309
2310 inline BinaryIterator Table::get_binary_iterator(size_t col_ndx, size_t ndx) const noexcept
2311 {
2312     return get<BinaryIterator>(col_ndx, ndx);
2313 }
2314
2315 inline void Table::set_binary(size_t col_ndx, size_t ndx, BinaryData value, bool is_default)
2316 {
2317     set(col_ndx, ndx, value, is_default);
2318 }
2319
2320 inline Mixed Table::get_mixed(size_t col_ndx, size_t ndx) const noexcept
2321 {
2322     return get<Mixed>(col_ndx, ndx);
2323 }
2324
2325 inline void Table::set_mixed(size_t col_ndx, size_t ndx, Mixed value, bool is_default)
2326 {
2327     set(col_ndx, ndx, value, is_default);
2328 }
2329
2330 inline void Table::set_null(size_t col_ndx, size_t ndx, bool is_default)
2331 {
2332     set(col_ndx, ndx, null(), is_default);
2333 }
2334
2335 inline void Table::set_null_unique(size_t col_ndx, size_t ndx)
2336 {
2337     set_unique(col_ndx, ndx, null());
2338 }
2339
2340
2341 // This class groups together information about the target of a link column
2342 // This is not a valid link if the target table == nullptr
2343 struct LinkTargetInfo {
2344     LinkTargetInfo(Table* target = nullptr, size_t backlink_ndx = realm::npos)
2345         : m_target_table(target)
2346         , m_backlink_col_ndx(backlink_ndx)
2347     {
2348     }
2349     bool is_valid() const
2350     {
2351         return (m_target_table != nullptr);
2352     }
2353     Table* m_target_table;
2354     size_t m_backlink_col_ndx; // a value of npos indicates the backlink should be appended
2355 };
2356
2357 // The purpose of this class is to give internal access to some, but
2358 // not all of the non-public parts of the Table class.
2359 class _impl::TableFriend {
2360 public:
2361     typedef Table::UnbindGuard UnbindGuard;
2362
2363     static ref_type create_empty_table(Allocator& alloc)
2364     {
2365         return Table::create_empty_table(alloc); // Throws
2366     }
2367
2368     static ref_type clone(const Table& table, Allocator& alloc)
2369     {
2370         return table.clone(alloc); // Throws
2371     }
2372
2373     static ref_type clone_columns(const Table& table, Allocator& alloc)
2374     {
2375         return table.clone_columns(alloc); // Throws
2376     }
2377
2378     static Table* create_accessor(Allocator& alloc, ref_type top_ref, Table::Parent* parent, size_t ndx_in_parent)
2379     {
2380         std::unique_ptr<Table> table(new Table(Table::ref_count_tag(), alloc)); // Throws
2381         table->init(top_ref, parent, ndx_in_parent);                            // Throws
2382         return table.release();
2383     }
2384
2385     static Table* create_accessor(Spec* shared_spec, Table::Parent* parent_column, size_t parent_row_ndx)
2386     {
2387         Allocator& alloc = shared_spec->get_alloc();
2388         std::unique_ptr<Table> table(new Table(Table::ref_count_tag(), alloc)); // Throws
2389         table->init(shared_spec, parent_column, parent_row_ndx);                // Throws
2390         return table.release();
2391     }
2392
2393     // Intended to be used only by Group::create_table_accessor()
2394     static Table* create_incomplete_accessor(Allocator& alloc, ref_type top_ref, Table::Parent* parent,
2395                                              size_t ndx_in_parent)
2396     {
2397         std::unique_ptr<Table> table(new Table(Table::ref_count_tag(), alloc)); // Throws
2398         bool skip_create_column_accessors = true;
2399         table->init(top_ref, parent, ndx_in_parent, skip_create_column_accessors); // Throws
2400         return table.release();
2401     }
2402
2403     // Intended to be used only by Group::create_table_accessor()
2404     static void complete_accessor(Table& table)
2405     {
2406         table.refresh_column_accessors(); // Throws
2407     }
2408
2409     static void set_top_parent(Table& table, ArrayParent* parent, size_t ndx_in_parent) noexcept
2410     {
2411         table.m_top.set_parent(parent, ndx_in_parent);
2412     }
2413
2414     static void update_from_parent(Table& table, size_t old_baseline) noexcept
2415     {
2416         table.update_from_parent(old_baseline);
2417     }
2418
2419     static void detach(Table& table) noexcept
2420     {
2421         table.detach();
2422     }
2423
2424     static void discard_row_accessors(Table& table) noexcept
2425     {
2426         table.discard_row_accessors();
2427     }
2428
2429     static void discard_child_accessors(Table& table) noexcept
2430     {
2431         table.discard_child_accessors();
2432     }
2433
2434     static void discard_subtable_accessor(Table& table, size_t col_ndx, size_t row_ndx) noexcept
2435     {
2436         table.discard_subtable_accessor(col_ndx, row_ndx);
2437     }
2438
2439     static void bind_ptr(Table& table) noexcept
2440     {
2441         table.bind_ptr();
2442     }
2443
2444     static void unbind_ptr(Table& table) noexcept
2445     {
2446         table.unbind_ptr();
2447     }
2448
2449     static bool compare_rows(const Table& a, const Table& b)
2450     {
2451         return a.compare_rows(b); // Throws
2452     }
2453
2454     static size_t get_size_from_ref(ref_type ref, Allocator& alloc) noexcept
2455     {
2456         return Table::get_size_from_ref(ref, alloc);
2457     }
2458
2459     static size_t get_size_from_ref(ref_type spec_ref, ref_type columns_ref, Allocator& alloc) noexcept
2460     {
2461         return Table::get_size_from_ref(spec_ref, columns_ref, alloc);
2462     }
2463
2464     static Spec& get_spec(Table& table) noexcept
2465     {
2466         return *table.m_spec;
2467     }
2468
2469     static const Spec& get_spec(const Table& table) noexcept
2470     {
2471         return *table.m_spec;
2472     }
2473
2474     static ColumnBase& get_column(const Table& table, size_t col_ndx)
2475     {
2476         return *table.m_cols[col_ndx];
2477     }
2478
2479     static void do_remove(Table& table, size_t row_ndx)
2480     {
2481         bool broken_reciprocal_backlinks = false;
2482         table.do_remove(row_ndx, broken_reciprocal_backlinks); // Throws
2483     }
2484
2485     static void do_move_last_over(Table& table, size_t row_ndx)
2486     {
2487         bool broken_reciprocal_backlinks = false;
2488         table.do_move_last_over(row_ndx, broken_reciprocal_backlinks); // Throws
2489     }
2490
2491     static void do_swap_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2)
2492     {
2493         table.do_swap_rows(row_ndx_1, row_ndx_2); // Throws
2494     }
2495
2496     static void do_move_row(Table& table, size_t from_ndx, size_t to_ndx)
2497     {
2498         table.do_move_row(from_ndx, to_ndx); // Throws
2499     }
2500
2501     static void do_merge_rows(Table& table, size_t row_ndx, size_t new_row_ndx)
2502     {
2503         table.do_merge_rows(row_ndx, new_row_ndx); // Throws
2504     }
2505
2506     static void do_clear(Table& table)
2507     {
2508         bool broken_reciprocal_backlinks = false;
2509         table.do_clear(broken_reciprocal_backlinks); // Throws
2510     }
2511
2512     static void do_set_link(Table& table, size_t col_ndx, size_t row_ndx, size_t target_row_ndx)
2513     {
2514         table.do_set_link(col_ndx, row_ndx, target_row_ndx); // Throws
2515     }
2516
2517     static size_t get_backlink_count(const Table& table, size_t row_ndx, bool only_strong_links) noexcept
2518     {
2519         return table.get_backlink_count(row_ndx, only_strong_links);
2520     }
2521
2522     static void cascade_break_backlinks_to(Table& table, size_t row_ndx, CascadeState& state)
2523     {
2524         table.cascade_break_backlinks_to(row_ndx, state); // Throws
2525     }
2526
2527     static void remove_backlink_broken_rows(Table& table, const CascadeState& rows)
2528     {
2529         table.remove_backlink_broken_rows(rows); // Throws
2530     }
2531
2532     static size_t* record_subtable_path(const Table& table, size_t* begin, size_t* end) noexcept
2533     {
2534         return table.record_subtable_path(begin, end);
2535     }
2536
2537     static void insert_column(Descriptor& desc, size_t column_ndx, DataType type, StringData name,
2538                               LinkTargetInfo& link, bool nullable = false)
2539     {
2540         Table::do_insert_column(desc, column_ndx, type, name, link, nullable); // Throws
2541     }
2542
2543     static void insert_column_unless_exists(Descriptor& desc, size_t column_ndx, DataType type, StringData name,
2544                                             LinkTargetInfo link, bool nullable = false, bool* was_inserted = nullptr)
2545     {
2546         Table::do_insert_column_unless_exists(desc, column_ndx, type, name, link, nullable, was_inserted); // Throws
2547     }
2548
2549     static void erase_column(Descriptor& desc, size_t column_ndx)
2550     {
2551         Table::do_erase_column(desc, column_ndx); // Throws
2552     }
2553
2554     static void rename_column(Descriptor& desc, size_t column_ndx, StringData name)
2555     {
2556         Table::do_rename_column(desc, column_ndx, name); // Throws
2557     }
2558
2559     static void add_search_index(Descriptor& desc, size_t column_ndx)
2560     {
2561         Table::do_add_search_index(desc, column_ndx); // Throws
2562     }
2563
2564     static void remove_search_index(Descriptor& desc, size_t column_ndx)
2565     {
2566         Table::do_remove_search_index(desc, column_ndx); // Throws
2567     }
2568
2569     static void set_link_type(Table& table, size_t column_ndx, LinkType link_type)
2570     {
2571         table.do_set_link_type(column_ndx, link_type); // Throws
2572     }
2573
2574     static void erase_row(Table& table, size_t row_ndx, bool is_move_last_over)
2575     {
2576         table.erase_row(row_ndx, is_move_last_over); // Throws
2577     }
2578
2579     static void batch_erase_rows(Table& table, const IntegerColumn& row_indexes, bool is_move_last_over)
2580     {
2581         table.batch_erase_rows(row_indexes, is_move_last_over); // Throws
2582     }
2583
2584     static TableRef get_subtable_accessor(Table& table, size_t col_ndx, size_t row_ndx) noexcept
2585     {
2586         return table.get_subtable_accessor(col_ndx, row_ndx);
2587     }
2588
2589     static const Table* get_link_target_table_accessor(const Table& table, size_t col_ndx) noexcept
2590     {
2591         return const_cast<Table&>(table).get_link_target_table_accessor(col_ndx);
2592     }
2593
2594     static Table* get_link_target_table_accessor(Table& table, size_t col_ndx) noexcept
2595     {
2596         return table.get_link_target_table_accessor(col_ndx);
2597     }
2598
2599     static void adj_acc_insert_rows(Table& table, size_t row_ndx, size_t num_rows) noexcept
2600     {
2601         table.adj_acc_insert_rows(row_ndx, num_rows);
2602     }
2603
2604     static void adj_acc_erase_row(Table& table, size_t row_ndx) noexcept
2605     {
2606         table.adj_acc_erase_row(row_ndx);
2607     }
2608
2609     static void adj_acc_swap_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2) noexcept
2610     {
2611         table.adj_acc_swap_rows(row_ndx_1, row_ndx_2);
2612     }
2613
2614     static void adj_acc_move_row(Table& table, size_t from_ndx, size_t to_ndx) noexcept
2615     {
2616         table.adj_acc_move_row(from_ndx, to_ndx);
2617     }
2618
2619     static void adj_acc_merge_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2) noexcept
2620     {
2621         table.adj_acc_merge_rows(row_ndx_1, row_ndx_2);
2622     }
2623
2624     static void adj_acc_move_over(Table& table, size_t from_row_ndx, size_t to_row_ndx) noexcept
2625     {
2626         table.adj_acc_move_over(from_row_ndx, to_row_ndx);
2627     }
2628
2629     static void adj_acc_clear_root_table(Table& table) noexcept
2630     {
2631         table.adj_acc_clear_root_table();
2632     }
2633
2634     static void adj_acc_clear_nonroot_table(Table& table) noexcept
2635     {
2636         table.adj_acc_clear_nonroot_table();
2637     }
2638
2639     static void adj_insert_column(Table& table, size_t col_ndx)
2640     {
2641         table.adj_insert_column(col_ndx); // Throws
2642     }
2643
2644     static void adj_add_column(Table& table)
2645     {
2646         size_t num_cols = table.m_cols.size();
2647         table.adj_insert_column(num_cols); // Throws
2648     }
2649
2650     static void adj_erase_column(Table& table, size_t col_ndx) noexcept
2651     {
2652         table.adj_erase_column(col_ndx);
2653     }
2654
2655     static bool is_marked(const Table& table) noexcept
2656     {
2657         return table.is_marked();
2658     }
2659
2660     static void mark(Table& table) noexcept
2661     {
2662         table.mark();
2663     }
2664
2665     static void unmark(Table& table) noexcept
2666     {
2667         table.unmark();
2668     }
2669
2670     static void recursive_mark(Table& table) noexcept
2671     {
2672         table.recursive_mark();
2673     }
2674
2675     static void mark_link_target_tables(Table& table, size_t col_ndx_begin) noexcept
2676     {
2677         table.mark_link_target_tables(col_ndx_begin);
2678     }
2679
2680     static void mark_opposite_link_tables(Table& table) noexcept
2681     {
2682         table.mark_opposite_link_tables();
2683     }
2684
2685     static DescriptorRef get_root_table_desc_accessor(Table& root_table) noexcept
2686     {
2687         return root_table.m_descriptor.lock();
2688     }
2689
2690     typedef Table::AccessorUpdater AccessorUpdater;
2691     static void update_accessors(Table& table, const size_t* col_path_begin, const size_t* col_path_end,
2692                                  AccessorUpdater& updater)
2693     {
2694         table.update_accessors(col_path_begin, col_path_end, updater); // Throws
2695     }
2696
2697     static void refresh_accessor_tree(Table& table)
2698     {
2699         table.refresh_accessor_tree(); // Throws
2700     }
2701
2702     static void refresh_spec_accessor(Table& table)
2703     {
2704         table.refresh_spec_accessor(); // Throws
2705     }
2706
2707     static void set_ndx_in_parent(Table& table, size_t ndx_in_parent) noexcept
2708     {
2709         table.set_ndx_in_parent(ndx_in_parent);
2710     }
2711
2712     static bool is_link_type(ColumnType type) noexcept
2713     {
2714         return Table::is_link_type(type);
2715     }
2716
2717     static void bump_version(Table& table, bool bump_global = true) noexcept
2718     {
2719         table.bump_version(bump_global);
2720     }
2721
2722     static bool is_cross_table_link_target(const Table& table)
2723     {
2724         return table.is_cross_table_link_target();
2725     }
2726
2727     static Group* get_parent_group(const Table& table) noexcept
2728     {
2729         return table.get_parent_group();
2730     }
2731
2732     static Replication* get_repl(Table& table) noexcept
2733     {
2734         return table.get_repl();
2735     }
2736
2737     static void register_view(Table& table, const TableViewBase* view)
2738     {
2739         table.register_view(view); // Throws
2740     }
2741
2742     static void unregister_view(Table& table, const TableViewBase* view) noexcept
2743     {
2744         table.unregister_view(view);
2745     }
2746 };
2747
2748
2749 } // namespace realm
2750
2751 #endif // REALM_TABLE_HPP