added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / column.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_COLUMN_HPP
20 #define REALM_COLUMN_HPP
21
22 #include <cstdint> // unint8_t etc
23 #include <cstdlib> // size_t
24 #include <vector>
25 #include <memory>
26
27 #include <realm/array_integer.hpp>
28 #include <realm/column_type.hpp>
29 #include <realm/column_fwd.hpp>
30 #include <realm/spec.hpp>
31 #include <realm/impl/output_stream.hpp>
32 #include <realm/query_conditions.hpp>
33 #include <realm/bptree.hpp>
34 #include <realm/index_string.hpp>
35 #include <realm/impl/destroy_guard.hpp>
36 #include <realm/exceptions.hpp>
37 #include <realm/table_ref.hpp>
38
39 namespace realm {
40
41
42 // Pre-definitions
43 struct CascadeState;
44 class StringIndex;
45
46 template <class T>
47 struct ImplicitNull;
48
49 template <class T>
50 struct ImplicitNull<util::Optional<T>> {
51     static constexpr bool value = true;
52 };
53
54 template <>
55 struct ImplicitNull<int64_t> {
56     static constexpr bool value = false;
57 };
58
59 template <>
60 struct ImplicitNull<float> {
61     static constexpr bool value = true;
62 };
63
64 template <>
65 struct ImplicitNull<double> {
66     static constexpr bool value = true;
67 };
68
69 // FIXME: Add specialization for ImplicitNull for float, double, StringData, BinaryData.
70
71 template <class T, class R, Action action, class Condition, class ColType>
72 R aggregate(const ColType& column, T target, size_t start, size_t end, size_t limit, size_t* return_ndx);
73
74
75 // Iterator with random access for Columns
76 template <typename ColumnDataType>
77 class ColumnRandIterator : public std::iterator<std::random_access_iterator_tag, ColumnDataType, ptrdiff_t, size_t> {
78 public:
79     ColumnRandIterator(const Column<ColumnDataType>* src_col, size_t ndx = 0);
80     bool operator==(const ColumnRandIterator<ColumnDataType>& rhs) const;
81     bool operator!=(const ColumnRandIterator<ColumnDataType>& rhs) const;
82     bool operator<(const ColumnRandIterator<ColumnDataType>& rhs) const;
83     bool operator>(const ColumnRandIterator<ColumnDataType>& rhs) const;
84     bool operator<=(const ColumnRandIterator<ColumnDataType>& rhs) const;
85     bool operator>=(const ColumnRandIterator<ColumnDataType>& rhs) const;
86     ColumnRandIterator<ColumnDataType>& operator+=(ptrdiff_t movement);
87     ColumnRandIterator<ColumnDataType>& operator-=(ptrdiff_t movement);
88     ColumnRandIterator<ColumnDataType>& operator++();
89     ColumnRandIterator<ColumnDataType>& operator--();
90     ColumnRandIterator<ColumnDataType> operator++(int);
91     ColumnRandIterator<ColumnDataType> operator--(int);
92     ColumnRandIterator<ColumnDataType> operator+(ptrdiff_t movement);
93     ColumnRandIterator<ColumnDataType> operator-(ptrdiff_t movement);
94     ptrdiff_t operator-(const ColumnRandIterator<ColumnDataType>& right) const;
95     const ColumnDataType operator*() const;
96     const ColumnDataType operator->() const;
97     const ColumnDataType operator[](ptrdiff_t offset) const;
98     size_t get_col_ndx() const;
99
100 protected:
101     size_t m_col_ndx;
102     const Column<ColumnDataType>* m_col;
103 };
104
105 /// Base class for all column types.
106 class ColumnBase {
107 public:
108     /// Get the number of entries in this column. This operation is relatively
109     /// slow.
110     virtual size_t size() const noexcept = 0;
111
112     /// \throw LogicError Thrown if this column is not string valued.
113     virtual void set_string(size_t row_ndx, StringData value);
114
115     /// Whether or not this column is nullable.
116     virtual bool is_nullable() const noexcept;
117
118     /// Whether or not the value at \a row_ndx is NULL. If the column is not
119     /// nullable, always returns false.
120     virtual bool is_null(size_t row_ndx) const noexcept;
121
122     /// Sets the value at \a row_ndx to be NULL.
123     /// \throw LogicError Thrown if this column is not nullable.
124     virtual void set_null(size_t row_ndx);
125
126     /// Inserts the specified number of elements into this column
127     /// starting at the specified row index. The new elements will have the
128     /// default value for the column type.
129     ///
130     /// \param row_ndx The row to start insertion at. If the row_ndx is less
131     /// than prior_num_rows then previous rows from row_ndx onwards will be
132     /// moved ahead by num_rows_to_insert.
133     ///
134     /// \param num_rows_to_insert The number of rows to insert. There is no
135     /// restriction on this value.
136     ///
137     /// \param prior_num_rows The number of elements in this column prior to the
138     /// modification.
139     ///
140     /// \param nullable Specifies whether or not this column is nullable. This
141     /// function may assert if nullable does not agree with \a is_nullable()
142     virtual void insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool nullable) = 0;
143
144     /// Removes the specified number of consecutive elements from
145     /// this column, starting at the specified row index.
146     ///
147     /// \param row_ndx The row to start removal at (inclusive). This must be
148     /// less than prior_num_rows.
149     ///
150     /// \param num_rows_to_erase The number of rows to erase.
151     /// The row_ndx + num_rows_to_erase must be less than prior_num_rows.
152     ///
153     /// \param prior_num_rows The number of elements in this column prior to the
154     /// modification.
155     ///
156     /// \param broken_reciprocal_backlinks If true, link columns must assume
157     /// that reciprocal backlinks have already been removed. Non-link columns
158     /// should ignore this argument.
159     virtual void erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows,
160                             bool broken_reciprocal_backlinks) = 0;
161
162     /// Removes the element at the specified row index by
163     /// moving the element at the last row index over it. This reduces the
164     /// number of elements by one.
165     ///
166     /// \param row_ndx The row to erase. Must be less than prior_num_rows.
167     ///
168     /// \param prior_num_rows The number of elements in this column prior to the
169     /// modification.
170     ///
171     /// \param broken_reciprocal_backlinks If true, link columns must assume
172     /// that reciprocal backlinks have already been removed. Non-link columns
173     /// should ignore this argument.
174     virtual void move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool broken_reciprocal_backlinks) = 0;
175
176     /// Remove all elements from this column.
177     ///
178     /// \param num_rows The total number of rows in this column.
179     ///
180     /// \param broken_reciprocal_backlinks If true, link columns must assume
181     /// that reciprocal backlinks have already been removed. Non-link columns
182     /// should ignore this argument.
183     virtual void clear(size_t num_rows, bool broken_reciprocal_backlinks) = 0;
184
185     /// \brief Swap the elements at the specified indices.
186     ///
187     /// Behaviour is undefined if:
188     /// - \a row_ndx_1 or \a row_ndx_2 point to an invalid element (out-of
189     /// bounds)
190     /// - \a row_ndx_1 and \a row_ndx_2 point to the same value
191     virtual void swap_rows(size_t row_ndx_1, size_t row_ndx_2) = 0;
192
193     virtual void destroy() noexcept = 0;
194     void move_assign(ColumnBase& col) noexcept;
195
196     virtual ~ColumnBase() noexcept
197     {
198     }
199
200     // Disable copying, this is not supported.
201     ColumnBase& operator=(const ColumnBase&) = delete;
202     ColumnBase(const ColumnBase&) = delete;
203
204     // Getter function for index. For integer index, the caller must supply a
205     // buffer that we can store the extracted value in (it may be bitpacked, so
206     // we cannot return a pointer in to the Array as we do with String index).
207     virtual StringData get_index_data(size_t, StringIndex::StringConversionBuffer& buffer) const noexcept = 0;
208
209     // Search index
210     virtual bool supports_search_index() const noexcept;
211     virtual bool has_search_index() const noexcept;
212     virtual StringIndex* create_search_index();
213     virtual void destroy_search_index() noexcept;
214     virtual const StringIndex* get_search_index() const noexcept;
215     virtual StringIndex* get_search_index() noexcept;
216     virtual void set_search_index_ref(ref_type, ArrayParent*, size_t ndx_in_parent);
217
218     virtual Allocator& get_alloc() const noexcept = 0;
219
220     /// Returns the 'ref' of the root array.
221     virtual ref_type get_ref() const noexcept = 0;
222     virtual MemRef get_mem() const noexcept = 0;
223
224     virtual void replace_root_array(std::unique_ptr<Array> leaf) = 0;
225     virtual MemRef clone_deep(Allocator& alloc) const = 0;
226     virtual void detach(void) = 0;
227     virtual bool is_attached(void) const noexcept = 0;
228
229     static size_t get_size_from_type_and_ref(ColumnType, ref_type, Allocator&, bool) noexcept;
230
231     // These assume that the right column compile-time type has been
232     // figured out.
233     static size_t get_size_from_ref(ref_type root_ref, Allocator&);
234     static size_t get_size_from_ref(ref_type spec_ref, ref_type columns_ref, Allocator&);
235
236     /// Write a slice of this column to the specified output stream.
237     virtual ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream&) const = 0;
238
239     /// Get this column's logical index within the containing table, or npos
240     /// for free-standing or non-top-level columns.
241     size_t get_column_index() const noexcept
242     {
243         return m_column_ndx;
244     }
245
246     virtual void set_parent(ArrayParent*, size_t ndx_in_parent) noexcept = 0;
247     virtual size_t get_ndx_in_parent() const noexcept = 0;
248     virtual void set_ndx_in_parent(size_t ndx_in_parent) noexcept = 0;
249
250     /// Called to update refs and memory pointers of this column accessor and
251     /// all its nested accessors, but only in cases where the logical contents
252     /// in strictly unchanged. Group::commit(), and
253     /// SharedGroup::commit_and_continue_as_read()() are examples of such
254     /// cases. In both those cases, the purpose is to keep user visible
255     /// accessors in a valid state across a commit.
256     virtual void update_from_parent(size_t old_baseline) noexcept = 0;
257
258     //@{
259
260     /// cascade_break_backlinks_to() is called iteratively for each column by
261     /// Table::cascade_break_backlinks_to() with the same arguments as are
262     /// passed to Table::cascade_break_backlinks_to(). Link columns must
263     /// override it. The same is true for cascade_break_backlinks_to_all_rows(),
264     /// except that it is called from
265     /// Table::cascade_break_backlinks_to_all_rows(), and that it expects
266     /// Table::cascade_break_backlinks_to_all_rows() to pass the number of rows
267     /// in the table as \a num_rows.
268
269     virtual void cascade_break_backlinks_to(size_t row_ndx, CascadeState&);
270     virtual void cascade_break_backlinks_to_all_rows(size_t num_rows, CascadeState&);
271
272     //@}
273
274     void discard_child_accessors() noexcept;
275
276     /// For columns that are able to contain subtables, this function returns
277     /// the pointer to the subtable accessor at the specified row index if it
278     /// exists, otherwise it returns null. For other column types, this function
279     /// returns null.
280     virtual TableRef get_subtable_accessor(size_t row_ndx) const noexcept;
281
282     /// Detach and remove the subtable accessor at the specified row if it
283     /// exists. For column types that are unable to contain subtable, this
284     /// function does nothing.
285     virtual void discard_subtable_accessor(size_t row_ndx) noexcept;
286
287     virtual void adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept;
288     virtual void adj_acc_erase_row(size_t row_ndx) noexcept;
289     /// See Table::adj_acc_move_over()
290     virtual void adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept;
291     virtual void adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept;
292     virtual void adj_acc_move_row(size_t from_ndx, size_t to_ndx) noexcept;
293     virtual void adj_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept;
294     virtual void adj_acc_clear_root_table() noexcept;
295
296     enum {
297         mark_Recursive = 0x01,
298         mark_LinkTargets = 0x02,
299         mark_LinkOrigins = 0x04,
300     };
301
302     virtual void mark(int type) noexcept;
303
304     virtual void bump_link_origin_table_version() noexcept;
305
306     virtual int compare_values(size_t row1, size_t row2) const noexcept = 0;
307
308     /// Refresh the dirty part of the accessor subtree rooted at this column
309     /// accessor.
310     ///
311     /// The following conditions are necessary and sufficient for the proper
312     /// operation of this function:
313     ///
314     ///  - The parent table accessor (excluding its column accessors) is in a
315     ///    valid state (already refreshed).
316     ///
317     ///  - Every subtable accessor in the subtree is marked dirty if it needs to
318     ///    be refreshed, or if it has a descendant accessor that needs to be
319     ///    refreshed.
320     ///
321     ///  - This column accessor, as well as all its descendant accessors, are in
322     ///    structural correspondence with the underlying node hierarchy whose
323     ///    root ref is stored in the parent (`Table::m_columns`) (see
324     ///    AccessorConsistencyLevels).
325     ///
326     ///  - The 'index in parent' property of the cached root array
327     ///    (`root->m_ndx_in_parent`) is valid.
328     virtual void refresh_accessor_tree(size_t new_col_ndx, const Spec&);
329
330     virtual void verify() const = 0;
331     virtual void verify(const Table&, size_t col_ndx) const;
332     virtual void to_dot(std::ostream&, StringData title = StringData()) const = 0;
333     virtual void do_dump_node_structure(std::ostream&, int level) const = 0;
334
335 #ifdef REALM_DEBUG
336     void dump_node_structure() const; // To std::cerr (for GDB)
337     void bptree_to_dot(const Array* root, std::ostream& out) const;
338 #endif
339
340 protected:
341     using SliceHandler = BpTreeBase::SliceHandler;
342
343     ColumnBase(size_t column_ndx = npos)
344         : m_column_ndx(column_ndx)
345     {
346     }
347     ColumnBase(ColumnBase&&) = default;
348
349     // Must not assume more than minimal consistency (see
350     // AccessorConsistencyLevels).
351     virtual void do_discard_child_accessors() noexcept
352     {
353     }
354
355     //@{
356     /// \tparam L Any type with an appropriate `value_type`, %size(),
357     /// and %get() members.
358     template <class L, class T>
359     size_t lower_bound(const L& list, T value) const noexcept;
360
361     template <class L, class T>
362     size_t upper_bound(const L& list, T value) const noexcept;
363     //@}
364
365     // Node functions
366
367     class CreateHandler {
368     public:
369         virtual ref_type create_leaf(size_t size) = 0;
370         ~CreateHandler() noexcept
371         {
372         }
373     };
374
375     static ref_type create(Allocator&, size_t size, CreateHandler&);
376
377     class LeafToDot;
378     virtual void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const = 0;
379
380     template <class Column>
381     static int compare_values(const Column* column, size_t row1, size_t row2) noexcept;
382
383 private:
384     size_t m_column_ndx = npos;
385
386     static ref_type build(size_t* rest_size_ptr, size_t fixed_height, Allocator&, CreateHandler&);
387 };
388
389
390 // FIXME: Temporary class until all column types have been migrated to use BpTree interface
391 class ColumnBaseSimple : public ColumnBase {
392 public:
393     //@{
394     /// Returns the array node at the root of this column, but note
395     /// that there is no guarantee that this node is an inner B+-tree
396     /// node or a leaf. This is the case for a MixedColumn in
397     /// particular.
398     Array* get_root_array() noexcept
399     {
400         return m_array.get();
401     }
402     const Array* get_root_array() const noexcept
403     {
404         return m_array.get();
405     }
406     //@}
407
408     Allocator& get_alloc() const noexcept final
409     {
410         return m_array->get_alloc();
411     }
412     void destroy() noexcept override
413     {
414         if (m_array)
415             m_array->destroy_deep();
416     }
417     ref_type get_ref() const noexcept final
418     {
419         return m_array->get_ref();
420     }
421     MemRef get_mem() const noexcept final
422     {
423         return m_array->get_mem();
424     }
425     void detach() noexcept final
426     {
427         m_array->detach();
428     }
429     bool is_attached() const noexcept final
430     {
431         return m_array->is_attached();
432     }
433     void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept final
434     {
435         m_array->set_parent(parent, ndx_in_parent);
436     }
437     size_t get_ndx_in_parent() const noexcept final
438     {
439         return m_array->get_ndx_in_parent();
440     }
441     void set_ndx_in_parent(size_t ndx_in_parent) noexcept override
442     {
443         m_array->set_ndx_in_parent(ndx_in_parent);
444     }
445     void update_from_parent(size_t old_baseline) noexcept override
446     {
447         m_array->update_from_parent(old_baseline);
448     }
449     MemRef clone_deep(Allocator& alloc) const override
450     {
451         return m_array->clone_deep(alloc);
452     }
453
454 protected:
455     ColumnBaseSimple(size_t column_ndx)
456         : ColumnBase(column_ndx)
457     {
458     }
459     ColumnBaseSimple(Array* root)
460         : m_array(root)
461     {
462     }
463     std::unique_ptr<Array> m_array;
464
465     void replace_root_array(std::unique_ptr<Array> new_root) final;
466     bool root_is_leaf() const noexcept
467     {
468         return !m_array->is_inner_bptree_node();
469     }
470
471     /// Introduce a new root node which increments the height of the
472     /// tree by one.
473     void introduce_new_root(ref_type new_sibling_ref, TreeInsertBase& state, bool is_append);
474
475     static ref_type write(const Array* root, size_t slice_offset, size_t slice_size, size_t table_size, SliceHandler&,
476                           _impl::OutputStream&);
477
478 #if defined(REALM_DEBUG)
479     void tree_to_dot(std::ostream&) const;
480 #endif
481 };
482
483 class ColumnBaseWithIndex : public ColumnBase {
484 public:
485     ~ColumnBaseWithIndex() noexcept override
486     {
487     }
488     void set_ndx_in_parent(size_t ndx) noexcept override;
489     void update_from_parent(size_t old_baseline) noexcept override;
490     void refresh_accessor_tree(size_t, const Spec&) override;
491     void move_assign(ColumnBaseWithIndex& col) noexcept;
492     void destroy() noexcept override;
493
494     virtual bool supports_search_index() const noexcept override
495     {
496         return true;
497     }
498     bool has_search_index() const noexcept final
499     {
500         return bool(m_search_index);
501     }
502     StringIndex* get_search_index() noexcept final
503     {
504         return m_search_index.get();
505     }
506     const StringIndex* get_search_index() const noexcept final
507     {
508         return m_search_index.get();
509     }
510     void destroy_search_index() noexcept override;
511     void set_search_index_ref(ref_type ref, ArrayParent* parent, size_t ndx_in_parent) final;
512     StringIndex* create_search_index() override = 0;
513
514 protected:
515     using ColumnBase::ColumnBase;
516     ColumnBaseWithIndex(ColumnBaseWithIndex&&) = default;
517     std::unique_ptr<StringIndex> m_search_index;
518 };
519
520
521 /// A column (Column) is a single B+-tree, and the root of
522 /// the column is the root of the B+-tree. All leaf nodes are arrays.
523 template <class T>
524 class Column : public ColumnBaseWithIndex {
525 public:
526     using value_type = T;
527     using LeafInfo = typename BpTree<T>::LeafInfo;
528     using LeafType = typename BpTree<T>::LeafType;
529
530     static constexpr bool nullable = ImplicitNull<T>::value;
531
532     struct unattached_root_tag {
533     };
534
535     explicit Column() noexcept
536         : ColumnBaseWithIndex(npos)
537         , m_tree(Allocator::get_default())
538     {
539     }
540     REALM_DEPRECATED("Initialize with ref instead") explicit Column(std::unique_ptr<Array> root) noexcept;
541     Column(Allocator&, ref_type, size_t column_ndx = npos);
542     Column(unattached_root_tag, Allocator&);
543     Column(Column&&) noexcept = default;
544     ~Column() noexcept override;
545
546     void init_from_parent();
547     void init_from_ref(Allocator&, ref_type);
548     void init_from_mem(Allocator&, MemRef);
549     // Accessor concept:
550     void destroy() noexcept override;
551     Allocator& get_alloc() const noexcept final;
552     ref_type get_ref() const noexcept final;
553     MemRef get_mem() const noexcept final;
554     void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept override;
555     size_t get_ndx_in_parent() const noexcept final;
556     void set_ndx_in_parent(size_t ndx) noexcept final;
557     void update_from_parent(size_t old_baseline) noexcept override;
558     void refresh_accessor_tree(size_t, const Spec&) override;
559     void detach() noexcept final;
560     bool is_attached() const noexcept final;
561     MemRef clone_deep(Allocator&) const override;
562
563     void move_assign(Column&);
564
565     static size_t get_size_from_ref(ref_type root_ref, Allocator& alloc)
566     {
567         return ColumnBase::get_size_from_ref(root_ref, alloc);
568     }
569
570     size_t size() const noexcept override;
571     bool is_empty() const noexcept
572     {
573         return size() == 0;
574     }
575     bool is_nullable() const noexcept override;
576
577     /// Provides access to the leaf that contains the element at the
578     /// specified index. Upon return \a ndx_in_leaf will be set to the
579     /// corresponding index relative to the beginning of the leaf.
580     ///
581     /// LeafInfo is a struct defined by the underlying BpTree<T>
582     /// data structure, that provides a way for the caller to do
583     /// leaf caching without instantiating too many objects along
584     /// the way.
585     ///
586     /// This function cannot be used for modifying operations as it
587     /// does not ensure the presence of an unbroken chain of parent
588     /// accessors. For this reason, the identified leaf should always
589     /// be accessed through the returned const-qualified reference,
590     /// and never directly through the specfied fallback accessor.
591     void get_leaf(size_t ndx, size_t& ndx_in_leaf, LeafInfo& inout_leaf) const noexcept;
592
593     // Getting and setting values
594     T get(size_t ndx) const noexcept;
595     bool is_null(size_t ndx) const noexcept override;
596     T back() const noexcept;
597     void set(size_t, T value);
598     void set_null(size_t) override;
599     void add(T value = T{});
600     void insert(size_t ndx, T value = T{}, size_t num_rows = 1);
601     void erase(size_t row_ndx);
602     void erase(size_t row_ndx, bool is_last);
603     void move_last_over(size_t row_ndx, size_t last_row_ndx);
604     void clear();
605
606     // Index support
607     StringData get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept override;
608
609     // FIXME: Remove these
610     uint64_t get_uint(size_t ndx) const noexcept;
611     ref_type get_as_ref(size_t ndx) const noexcept;
612     void set_uint(size_t ndx, uint64_t value);
613     void set_as_ref(size_t ndx, ref_type value);
614
615     template <class U>
616     void adjust(size_t ndx, U diff);
617
618     template <class U>
619     void adjust(U diff);
620
621     template <class U>
622     void adjust_ge(T limit, U diff);
623
624     size_t count(T target) const;
625
626     typename ColumnTypeTraits<T>::sum_type sum(size_t start = 0, size_t end = npos, size_t limit = npos,
627                                                size_t* return_ndx = nullptr) const;
628
629     typename ColumnTypeTraits<T>::minmax_type maximum(size_t start = 0, size_t end = npos, size_t limit = npos,
630                                                       size_t* return_ndx = nullptr) const;
631
632     typename ColumnTypeTraits<T>::minmax_type minimum(size_t start = 0, size_t end = npos, size_t limit = npos,
633                                                       size_t* return_ndx = nullptr) const;
634
635     double average(size_t start = 0, size_t end = npos, size_t limit = npos, size_t* return_ndx = nullptr) const;
636
637     size_t find_first(T value, size_t begin = 0, size_t end = npos) const;
638     void find_all(Column<int64_t>& out_indices, T value, size_t begin = 0, size_t end = npos) const;
639
640     void populate_search_index();
641     StringIndex* create_search_index() override;
642     inline bool supports_search_index() const noexcept override
643     {
644         if (realm::is_any<T, float, double>::value)
645             return false;
646         else
647             return true;
648     }
649
650
651     //@{
652     /// Find the lower/upper bound for the specified value assuming
653     /// that the elements are already sorted in ascending order
654     /// according to ordinary integer comparison.
655     size_t lower_bound(T value) const noexcept;
656     size_t upper_bound(T value) const noexcept;
657     //@}
658
659     using const_iterator = ColumnRandIterator<T>;
660
661     const_iterator cbegin() const
662     {
663         return const_iterator(this, 0); // `this` is const in a const method
664     }
665     const_iterator cend() const
666     {
667         return const_iterator(this, size());
668     }
669
670     size_t find_gte(T target, size_t start) const;
671
672     bool compare(const Column&) const noexcept;
673     int compare_values(size_t row1, size_t row2) const noexcept override;
674
675     static ref_type create(Allocator&, Array::Type leaf_type = Array::type_Normal, size_t size = 0, T value = T{});
676
677     // Overriding method in ColumnBase
678     ref_type write(size_t, size_t, size_t, _impl::OutputStream&) const override;
679
680     void insert_rows(size_t, size_t, size_t, bool) override;
681     void erase_rows(size_t, size_t, size_t, bool) override;
682     void move_last_row_over(size_t, size_t, bool) override;
683
684     /// \brief Swap the elements at the specified indices.
685     ///
686     /// If this \c Column has a search index defined, it will be updated to
687     /// reflect the changes induced by the swap.
688     ///
689     /// Behaviour is undefined if:
690     /// - \a row_ndx_1 or \a row_ndx_2 point to an invalid element (out-of
691     /// bounds)
692     /// - \a row_ndx_1 and \a row_ndx_2 point to the same value
693     void swap_rows(size_t, size_t) override;
694     void clear(size_t, bool) override;
695
696     /// \param row_ndx Must be `realm::npos` if appending.
697     /// \param value The value to store at the specified row.
698     /// \param num_rows The number of rows to insert.
699     void insert_without_updating_index(size_t row_ndx, T value, size_t num_rows);
700
701     void verify() const override;
702     void to_dot(std::ostream&, StringData title) const override;
703     void do_dump_node_structure(std::ostream&, int) const override;
704 #ifdef REALM_DEBUG
705     using ColumnBase::verify;
706     void tree_to_dot(std::ostream&) const;
707     MemStats stats() const;
708 #endif
709
710     //@{
711     /// Returns the array node at the root of this column, but note
712     /// that there is no guarantee that this node is an inner B+-tree
713     /// node or a leaf. This is the case for a MixedColumn in
714     /// particular.
715     Array* get_root_array() noexcept
716     {
717         return &m_tree.root();
718     }
719     const Array* get_root_array() const noexcept
720     {
721         return &m_tree.root();
722     }
723     //@}
724
725 protected:
726     bool root_is_leaf() const noexcept
727     {
728         return m_tree.root_is_leaf();
729     }
730     void replace_root_array(std::unique_ptr<Array> leaf) final
731     {
732         m_tree.replace_root(std::move(leaf));
733     }
734
735     void set_without_updating_index(size_t row_ndx, T value);
736     void erase_without_updating_index(size_t row_ndx, bool is_last);
737     void move_last_over_without_updating_index(size_t row_ndx, size_t last_row_ndx);
738     void swap_rows_without_updating_index(size_t row_ndx_1, size_t row_ndx_2);
739
740     /// If any element points to an array node, this function recursively
741     /// destroys that array node. Note that the same is **not** true for
742     /// IntegerColumn::do_erase() and IntegerColumn::do_move_last_over().
743     ///
744     /// FIXME: Be careful, clear_without_updating_index() currently forgets
745     /// if the leaf type is Array::type_HasRefs.
746     void clear_without_updating_index();
747
748     void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override;
749 #ifdef REALM_DEBUG
750     static void dump_node_structure(const Array& root, std::ostream&, int level);
751 #endif
752     std::pair<ref_type, size_t> get_to_dot_parent(size_t ndx_in_parent) const;
753
754 private:
755     class EraseLeafElem;
756     class CreateHandler;
757     class SliceHandler;
758
759     friend class Array;
760     friend class ColumnBase;
761     friend class StringIndex;
762
763     BpTree<T> m_tree;
764
765     void do_erase(size_t row_ndx, size_t num_rows_to_erase, bool is_last);
766 };
767
768 // Implementation:
769
770
771 template <>
772 inline size_t IntNullColumn::get_size_from_ref(ref_type root_ref, Allocator& alloc)
773 {
774     // FIXME: Speed improvement possible by not creating instance, but tricky! This slow method is OK so far
775     // because it's only invoked by Table::get_size_from_ref() which is only used for subtables which we
776     // currently 2016) do not expose publicly.
777     IntNullColumn inc(alloc, root_ref);
778     return inc.size();
779 }
780
781
782 inline bool ColumnBase::supports_search_index() const noexcept
783 {
784     REALM_ASSERT(!has_search_index());
785     return false;
786 }
787
788 inline bool ColumnBase::has_search_index() const noexcept
789 {
790     return get_search_index() != nullptr;
791 }
792
793 inline StringIndex* ColumnBase::create_search_index()
794 {
795     return nullptr;
796 }
797
798 inline void ColumnBase::destroy_search_index() noexcept
799 {
800 }
801
802 inline const StringIndex* ColumnBase::get_search_index() const noexcept
803 {
804     return nullptr;
805 }
806
807 inline StringIndex* ColumnBase::get_search_index() noexcept
808 {
809     return nullptr;
810 }
811
812 inline void ColumnBase::set_search_index_ref(ref_type, ArrayParent*, size_t)
813 {
814 }
815
816 inline void ColumnBase::discard_child_accessors() noexcept
817 {
818     do_discard_child_accessors();
819 }
820
821 inline void ColumnBase::discard_subtable_accessor(size_t) noexcept
822 {
823     // Noop
824 }
825
826 inline void ColumnBase::adj_acc_insert_rows(size_t, size_t) noexcept
827 {
828     // Noop
829 }
830
831 inline void ColumnBase::adj_acc_erase_row(size_t) noexcept
832 {
833     // Noop
834 }
835
836 inline void ColumnBase::adj_acc_move_over(size_t, size_t) noexcept
837 {
838     // Noop
839 }
840
841 inline void ColumnBase::adj_acc_swap_rows(size_t, size_t) noexcept
842 {
843     // Noop
844 }
845
846 inline void ColumnBase::adj_acc_move_row(size_t, size_t) noexcept
847 {
848     // Noop
849 }
850
851 inline void ColumnBase::adj_acc_merge_rows(size_t, size_t) noexcept
852 {
853     // Noop
854 }
855
856 inline void ColumnBase::adj_acc_clear_root_table() noexcept
857 {
858     // Noop
859 }
860
861 inline void ColumnBase::mark(int) noexcept
862 {
863     // Noop
864 }
865
866 inline void ColumnBase::bump_link_origin_table_version() noexcept
867 {
868     // Noop
869 }
870
871 template <class Column>
872 int ColumnBase::compare_values(const Column* column, size_t row1, size_t row2) noexcept
873 {
874     // we negate nullability such that the two ternary statements in this method can look identical to reduce
875     // risk of bugs
876     bool v1 = !column->is_null(row1);
877     bool v2 = !column->is_null(row2);
878
879     if (!v1 || !v2)
880         return v1 == v2 ? 0 : v1 < v2 ? 1 : -1;
881
882     auto a = column->get(row1);
883     auto b = column->get(row2);
884     return a == b ? 0 : a < b ? 1 : -1;
885 }
886
887 template <class T>
888 void Column<T>::set_without_updating_index(size_t ndx, T value)
889 {
890     m_tree.set(ndx, std::move(value));
891 }
892
893 template <class T>
894 void Column<T>::set(size_t ndx, T value)
895 {
896     REALM_ASSERT_DEBUG(ndx < size());
897     if (has_search_index()) {
898         m_search_index->set(ndx, value);
899     }
900     set_without_updating_index(ndx, std::move(value));
901 }
902
903 template <class T>
904 void Column<T>::set_null(size_t ndx)
905 {
906     REALM_ASSERT_DEBUG(ndx < size());
907     if (!is_nullable()) {
908         throw LogicError{LogicError::column_not_nullable};
909     }
910     if (has_search_index()) {
911         m_search_index->set(ndx, null{});
912     }
913     m_tree.set_null(ndx);
914 }
915
916 // When a value of a signed type is converted to an unsigned type, the C++ standard guarantees that negative values
917 // are converted from the native representation to 2's complement, but the opposite conversion is left as undefined.
918 // realm::util::from_twos_compl() is used here to perform the correct opposite unsigned-to-signed conversion,
919 // which reduces to a no-op when 2's complement is the native representation of negative values.
920 template <class T>
921 void Column<T>::set_uint(size_t ndx, uint64_t value)
922 {
923     set(ndx, util::from_twos_compl<int_fast64_t>(value));
924 }
925
926 template <class T>
927 void Column<T>::set_as_ref(size_t ndx, ref_type ref)
928 {
929     set(ndx, from_ref(ref));
930 }
931
932 template <class T>
933 template <class U>
934 void Column<T>::adjust(size_t ndx, U diff)
935 {
936     REALM_ASSERT_3(ndx, <, size());
937     m_tree.adjust(ndx, diff);
938 }
939
940 template <class T>
941 template <class U>
942 void Column<T>::adjust(U diff)
943 {
944     m_tree.adjust(diff);
945 }
946
947 template <class T>
948 template <class U>
949 void Column<T>::adjust_ge(T limit, U diff)
950 {
951     m_tree.adjust_ge(limit, diff);
952 }
953
954 template <class T>
955 size_t Column<T>::count(T target) const
956 {
957     if (has_search_index()) {
958         return m_search_index->count(target);
959     }
960     return to_size_t(aggregate<T, int64_t, act_Count, Equal>(*this, target, 0, size(), npos, nullptr));
961 }
962
963 template <class T>
964 typename ColumnTypeTraits<T>::sum_type Column<T>::sum(size_t start, size_t end, size_t limit,
965                                                       size_t* return_ndx) const
966 {
967     using sum_type = typename ColumnTypeTraits<T>::sum_type;
968     if (nullable)
969         return aggregate<T, sum_type, act_Sum, NotNull>(*this, 0, start, end, limit, return_ndx);
970     else
971         return aggregate<T, sum_type, act_Sum, None>(*this, 0, start, end, limit, return_ndx);
972 }
973
974 template <class T>
975 double Column<T>::average(size_t start, size_t end, size_t limit, size_t* return_ndx) const
976 {
977     if (end == size_t(-1))
978         end = size();
979
980     auto s = sum(start, end, limit);
981     size_t cnt = to_size_t(aggregate<T, int64_t, act_Count, NotNull>(*this, 0, start, end, limit, nullptr));
982     if (return_ndx)
983         *return_ndx = cnt;
984     double avg = double(s) / (cnt == 0 ? 1 : cnt);
985     return avg;
986 }
987
988 template <class T>
989 typename ColumnTypeTraits<T>::minmax_type Column<T>::minimum(size_t start, size_t end, size_t limit,
990                                                              size_t* return_ndx) const
991 {
992     using R = typename ColumnTypeTraits<T>::minmax_type;
993     return aggregate<T, R, act_Min, NotNull>(*this, 0, start, end, limit, return_ndx);
994 }
995
996 template <class T>
997 typename ColumnTypeTraits<T>::minmax_type Column<T>::maximum(size_t start, size_t end, size_t limit,
998                                                              size_t* return_ndx) const
999 {
1000     using R = typename ColumnTypeTraits<T>::minmax_type;
1001     return aggregate<T, R, act_Max, NotNull>(*this, 0, start, end, limit, return_ndx);
1002 }
1003
1004 template <class T>
1005 void Column<T>::get_leaf(size_t ndx, size_t& ndx_in_leaf, LeafInfo& inout_leaf_info) const noexcept
1006 {
1007     m_tree.get_leaf(ndx, ndx_in_leaf, inout_leaf_info);
1008 }
1009
1010 template <class T>
1011 StringData Column<T>::get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept
1012 {
1013     T x = get(ndx);
1014     return to_str(x, buffer);
1015 }
1016
1017 template <class T>
1018 void Column<T>::populate_search_index()
1019 {
1020     REALM_ASSERT(has_search_index());
1021     // Populate the index
1022     size_t num_rows = size();
1023     for (size_t row_ndx = 0; row_ndx != num_rows; ++row_ndx) {
1024         bool is_append = true;
1025         if (is_null(row_ndx)) {
1026             m_search_index->insert(row_ndx, null{}, 1, is_append); // Throws
1027         }
1028         else {
1029             T value = get(row_ndx);
1030             m_search_index->insert(row_ndx, value, 1, is_append); // Throws
1031         }
1032     }
1033 }
1034
1035 template <class T>
1036 StringIndex* Column<T>::create_search_index()
1037 {
1038     if (realm::is_any<T, float, double>::value)
1039         return nullptr;
1040
1041     REALM_ASSERT(!has_search_index());
1042     REALM_ASSERT(supports_search_index());
1043     m_search_index.reset(new StringIndex(this, get_alloc())); // Throws
1044     populate_search_index();
1045     return m_search_index.get();
1046 }
1047
1048 template <class T>
1049 size_t Column<T>::find_first(T value, size_t begin, size_t end) const
1050 {
1051     REALM_ASSERT_3(begin, <=, size());
1052     REALM_ASSERT(end == npos || (begin <= end && end <= size()));
1053
1054     if (m_search_index && begin == 0 && end == npos)
1055         return m_search_index->find_first(value);
1056     return m_tree.find_first(value, begin, end);
1057 }
1058
1059 template <class T>
1060 void Column<T>::find_all(IntegerColumn& result, T value, size_t begin, size_t end) const
1061 {
1062     REALM_ASSERT_3(begin, <=, size());
1063     REALM_ASSERT(end == npos || (begin <= end && end <= size()));
1064
1065     if (m_search_index && begin == 0 && end == npos)
1066         return m_search_index->find_all(result, value);
1067     return m_tree.find_all(result, value, begin, end);
1068 }
1069
1070 inline size_t ColumnBase::get_size_from_ref(ref_type root_ref, Allocator& alloc)
1071 {
1072     const char* root_header = alloc.translate(root_ref);
1073     bool root_is_leaf = !Array::get_is_inner_bptree_node_from_header(root_header);
1074     if (root_is_leaf)
1075         return Array::get_size_from_header(root_header);
1076     return BpTreeNode::get_bptree_size_from_header(root_header);
1077 }
1078
1079 template <class L, class T>
1080 size_t ColumnBase::lower_bound(const L& list, T value) const noexcept
1081 {
1082     size_t i = 0;
1083     size_t list_size = list.size();
1084     while (0 < list_size) {
1085         size_t half = list_size / 2;
1086         size_t mid = i + half;
1087         typename L::value_type probe = list.get(mid);
1088         if (probe < value) {
1089             i = mid + 1;
1090             list_size -= half + 1;
1091         }
1092         else {
1093             list_size = half;
1094         }
1095     }
1096     return i;
1097 }
1098
1099 template <class L, class T>
1100 size_t ColumnBase::upper_bound(const L& list, T value) const noexcept
1101 {
1102     size_t i = 0;
1103     size_t list_size = list.size();
1104     while (0 < list_size) {
1105         size_t half = list_size / 2;
1106         size_t mid = i + half;
1107         typename L::value_type probe = list.get(mid);
1108         if (!(value < probe)) {
1109             i = mid + 1;
1110             list_size -= half + 1;
1111         }
1112         else {
1113             list_size = half;
1114         }
1115     }
1116     return i;
1117 }
1118
1119
1120 inline ref_type ColumnBase::create(Allocator& alloc, size_t column_size, CreateHandler& handler)
1121 {
1122     size_t rest_size = column_size;
1123     size_t fixed_height = 0; // Not fixed
1124     return build(&rest_size, fixed_height, alloc, handler);
1125 }
1126
1127 template <class T>
1128 Column<T>::Column(Allocator& alloc, ref_type ref, size_t column_ndx)
1129     : ColumnBaseWithIndex(column_ndx)
1130     , m_tree(BpTreeBase::unattached_tag{})
1131 {
1132     // fixme, must m_search_index be copied here?
1133     m_tree.init_from_ref(alloc, ref);
1134 }
1135
1136 template <class T>
1137 Column<T>::Column(unattached_root_tag, Allocator& alloc)
1138     : ColumnBaseWithIndex(npos)
1139     , m_tree(alloc)
1140 {
1141 }
1142
1143 template <class T>
1144 Column<T>::Column(std::unique_ptr<Array> root) noexcept
1145     : m_tree(std::move(root))
1146 {
1147 }
1148
1149 template <class T>
1150 Column<T>::~Column() noexcept
1151 {
1152 }
1153
1154 template <class T>
1155 void Column<T>::init_from_parent()
1156 {
1157     m_tree.init_from_parent();
1158 }
1159
1160 template <class T>
1161 void Column<T>::init_from_ref(Allocator& alloc, ref_type ref)
1162 {
1163     m_tree.init_from_ref(alloc, ref);
1164 }
1165
1166 template <class T>
1167 void Column<T>::init_from_mem(Allocator& alloc, MemRef mem)
1168 {
1169     m_tree.init_from_mem(alloc, mem);
1170 }
1171
1172 template <class T>
1173 void Column<T>::destroy() noexcept
1174 {
1175     ColumnBaseWithIndex::destroy();
1176     m_tree.destroy();
1177 }
1178
1179 template <class T>
1180 void Column<T>::move_assign(Column<T>& col)
1181 {
1182     ColumnBaseWithIndex::move_assign(col);
1183     m_tree = std::move(col.m_tree);
1184 }
1185
1186 template <class T>
1187 Allocator& Column<T>::get_alloc() const noexcept
1188 {
1189     return m_tree.get_alloc();
1190 }
1191
1192 template <class T>
1193 void Column<T>::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept
1194 {
1195     m_tree.set_parent(parent, ndx_in_parent);
1196 }
1197
1198 template <class T>
1199 size_t Column<T>::get_ndx_in_parent() const noexcept
1200 {
1201     return m_tree.get_ndx_in_parent();
1202 }
1203
1204 template <class T>
1205 void Column<T>::set_ndx_in_parent(size_t ndx_in_parent) noexcept
1206 {
1207     ColumnBaseWithIndex::set_ndx_in_parent(ndx_in_parent);
1208     m_tree.set_ndx_in_parent(ndx_in_parent);
1209 }
1210
1211 template <class T>
1212 void Column<T>::detach() noexcept
1213 {
1214     m_tree.detach();
1215 }
1216
1217 template <class T>
1218 bool Column<T>::is_attached() const noexcept
1219 {
1220     return m_tree.is_attached();
1221 }
1222
1223 template <class T>
1224 ref_type Column<T>::get_ref() const noexcept
1225 {
1226     return get_root_array()->get_ref();
1227 }
1228
1229 template <class T>
1230 MemRef Column<T>::get_mem() const noexcept
1231 {
1232     return get_root_array()->get_mem();
1233 }
1234
1235 template <class T>
1236 void Column<T>::update_from_parent(size_t old_baseline) noexcept
1237 {
1238     ColumnBaseWithIndex::update_from_parent(old_baseline);
1239     m_tree.update_from_parent(old_baseline);
1240 }
1241
1242 template <class T>
1243 MemRef Column<T>::clone_deep(Allocator& alloc) const
1244 {
1245     return m_tree.clone_deep(alloc);
1246 }
1247
1248 template <class T>
1249 size_t Column<T>::size() const noexcept
1250 {
1251     return m_tree.size();
1252 }
1253
1254 template <class T>
1255 bool Column<T>::is_nullable() const noexcept
1256 {
1257     return nullable;
1258 }
1259
1260 template <class T>
1261 T Column<T>::get(size_t ndx) const noexcept
1262 {
1263     return m_tree.get(ndx);
1264 }
1265
1266 template <class T>
1267 bool Column<T>::is_null(size_t ndx) const noexcept
1268 {
1269     return nullable && m_tree.is_null(ndx);
1270 }
1271
1272 template <class T>
1273 T Column<T>::back() const noexcept
1274 {
1275     return m_tree.back();
1276 }
1277
1278 template <class T>
1279 ref_type Column<T>::get_as_ref(size_t ndx) const noexcept
1280 {
1281     return to_ref(get(ndx));
1282 }
1283
1284 template <class T>
1285 uint64_t Column<T>::get_uint(size_t ndx) const noexcept
1286 {
1287     static_assert(std::is_convertible<T, uint64_t>::value, "T is not convertible to uint.");
1288     return static_cast<uint64_t>(get(ndx));
1289 }
1290
1291 template <class T>
1292 void Column<T>::add(T value)
1293 {
1294     insert(npos, std::move(value));
1295 }
1296
1297 template <class T>
1298 void Column<T>::insert_without_updating_index(size_t row_ndx, T value, size_t num_rows)
1299 {
1300     size_t column_size = this->size(); // Slow
1301     bool is_append = row_ndx == column_size || row_ndx == npos;
1302     size_t ndx_or_npos_if_append = is_append ? npos : row_ndx;
1303
1304     m_tree.insert(ndx_or_npos_if_append, std::move(value), num_rows); // Throws
1305 }
1306
1307 template <class T>
1308 void Column<T>::insert(size_t row_ndx, T value, size_t num_rows)
1309 {
1310     size_t column_size = this->size(); // Slow
1311     bool is_append = row_ndx == column_size || row_ndx == npos;
1312     size_t ndx_or_npos_if_append = is_append ? npos : row_ndx;
1313
1314     m_tree.insert(ndx_or_npos_if_append, value, num_rows); // Throws
1315
1316     if (has_search_index()) {
1317         row_ndx = is_append ? column_size : row_ndx;
1318         m_search_index->insert(row_ndx, value, num_rows, is_append); // Throws
1319     }
1320 }
1321
1322 template <class T>
1323 void Column<T>::erase_without_updating_index(size_t row_ndx, bool is_last)
1324 {
1325     m_tree.erase(row_ndx, is_last);
1326 }
1327
1328 template <class T>
1329 void Column<T>::erase(size_t row_ndx)
1330 {
1331     REALM_ASSERT(size() >= 1);
1332     size_t last_row_ndx = size() - 1; // Note that size() is slow
1333     bool is_last = (row_ndx == last_row_ndx);
1334     erase(row_ndx, is_last); // Throws
1335 }
1336
1337 template <class T>
1338 void Column<T>::erase(size_t row_ndx, bool is_last)
1339 {
1340     size_t num_rows_to_erase = 1;
1341     do_erase(row_ndx, num_rows_to_erase, is_last); // Throws
1342 }
1343
1344 template <class T>
1345 void Column<T>::move_last_over_without_updating_index(size_t row_ndx, size_t last_row_ndx)
1346 {
1347     m_tree.move_last_over(row_ndx, last_row_ndx);
1348 }
1349
1350 template <class T>
1351 void Column<T>::move_last_over(size_t row_ndx, size_t last_row_ndx)
1352 {
1353     REALM_ASSERT_3(row_ndx, <=, last_row_ndx);
1354     REALM_ASSERT_DEBUG(last_row_ndx + 1 == size());
1355
1356     if (has_search_index()) {
1357         // remove the value to be overwritten from index
1358         bool is_last = true; // This tells StringIndex::erase() to not adjust subsequent indexes
1359         m_search_index->erase<StringData>(row_ndx, is_last); // Throws
1360
1361         // update index to point to new location
1362         if (row_ndx != last_row_ndx) {
1363             T moved_value = get(last_row_ndx);
1364             m_search_index->update_ref(moved_value, last_row_ndx, row_ndx); // Throws
1365         }
1366     }
1367
1368     move_last_over_without_updating_index(row_ndx, last_row_ndx);
1369 }
1370
1371 template <class T>
1372 void Column<T>::swap_rows(size_t row_ndx_1, size_t row_ndx_2)
1373 {
1374     REALM_ASSERT_3(row_ndx_1, <, size());
1375     REALM_ASSERT_3(row_ndx_2, <, size());
1376     REALM_ASSERT_DEBUG(row_ndx_1 != row_ndx_2);
1377
1378     if (has_search_index()) {
1379         T value_1 = get(row_ndx_1);
1380         T value_2 = get(row_ndx_2);
1381         size_t column_size = this->size();
1382         bool row_ndx_1_is_last = row_ndx_1 == column_size - 1;
1383         bool row_ndx_2_is_last = row_ndx_2 == column_size - 1;
1384         m_search_index->erase<StringData>(row_ndx_1, row_ndx_1_is_last);
1385         m_search_index->insert(row_ndx_1, value_2, 1, row_ndx_1_is_last);
1386
1387         m_search_index->erase<StringData>(row_ndx_2, row_ndx_2_is_last);
1388         m_search_index->insert(row_ndx_2, value_1, 1, row_ndx_2_is_last);
1389     }
1390
1391     swap_rows_without_updating_index(row_ndx_1, row_ndx_2);
1392 }
1393
1394 template <class T>
1395 void Column<T>::swap_rows_without_updating_index(size_t row_ndx_1, size_t row_ndx_2)
1396 {
1397     // FIXME: This can be optimized with direct getters and setters.
1398     T value_1 = get(row_ndx_1);
1399     T value_2 = get(row_ndx_2);
1400     m_tree.set(row_ndx_1, value_2);
1401     m_tree.set(row_ndx_2, value_1);
1402 }
1403
1404 template <class T>
1405 void Column<T>::clear_without_updating_index()
1406 {
1407     m_tree.clear(); // Throws
1408 }
1409
1410 template <class T>
1411 void Column<T>::clear()
1412 {
1413     if (has_search_index()) {
1414         m_search_index->clear();
1415     }
1416     clear_without_updating_index();
1417 }
1418
1419 template <class T, class Enable = void>
1420 struct NullOrDefaultValue;
1421 template <class T>
1422 struct NullOrDefaultValue<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
1423     static T null_or_default_value(bool is_null)
1424     {
1425         if (is_null) {
1426             return null::get_null_float<T>();
1427         }
1428         else {
1429             return T{};
1430         }
1431     }
1432 };
1433 template <class T>
1434 struct NullOrDefaultValue<util::Optional<T>, void> {
1435     static util::Optional<T> null_or_default_value(bool is_null)
1436     {
1437         if (is_null) {
1438             return util::none;
1439         }
1440         else {
1441             return util::some<T>(T{});
1442         }
1443     }
1444 };
1445 template <class T>
1446 struct NullOrDefaultValue<T, typename std::enable_if<!ImplicitNull<T>::value>::type> {
1447     static T null_or_default_value(bool is_null)
1448     {
1449         REALM_ASSERT(!is_null);
1450         return T{};
1451     }
1452 };
1453
1454 // Implementing pure virtual method of ColumnBase.
1455 template <class T>
1456 void Column<T>::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool insert_nulls)
1457 {
1458     REALM_ASSERT_DEBUG(prior_num_rows == size());
1459     REALM_ASSERT(row_ndx <= prior_num_rows);
1460
1461     size_t row_ndx_2 = (row_ndx == prior_num_rows ? realm::npos : row_ndx);
1462     T value = NullOrDefaultValue<T>::null_or_default_value(insert_nulls);
1463     insert(row_ndx_2, value, num_rows_to_insert); // Throws
1464 }
1465
1466 // Implementing pure virtual method of ColumnBase.
1467 template <class T>
1468 void Column<T>::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool)
1469 {
1470     REALM_ASSERT_DEBUG(prior_num_rows == size());
1471     REALM_ASSERT(num_rows_to_erase <= prior_num_rows);
1472     REALM_ASSERT(row_ndx <= prior_num_rows - num_rows_to_erase);
1473
1474     bool is_last = (row_ndx + num_rows_to_erase == prior_num_rows);
1475     do_erase(row_ndx, num_rows_to_erase, is_last); // Throws
1476 }
1477
1478 // Implementing pure virtual method of ColumnBase.
1479 template <class T>
1480 void Column<T>::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool)
1481 {
1482     REALM_ASSERT_DEBUG(prior_num_rows == size());
1483     REALM_ASSERT(row_ndx < prior_num_rows);
1484
1485     size_t last_row_ndx = prior_num_rows - 1;
1486     move_last_over(row_ndx, last_row_ndx); // Throws
1487 }
1488
1489 // Implementing pure virtual method of ColumnBase.
1490 template <class T>
1491 void Column<T>::clear(size_t, bool)
1492 {
1493     clear(); // Throws
1494 }
1495
1496
1497 template <class T>
1498 size_t Column<T>::lower_bound(T value) const noexcept
1499 {
1500     if (root_is_leaf()) {
1501         auto root = static_cast<const LeafType*>(get_root_array());
1502         return root->lower_bound(value);
1503     }
1504     return ColumnBase::lower_bound(*this, value);
1505 }
1506
1507 template <class T>
1508 size_t Column<T>::upper_bound(T value) const noexcept
1509 {
1510     if (root_is_leaf()) {
1511         auto root = static_cast<const LeafType*>(get_root_array());
1512         return root->upper_bound(value);
1513     }
1514     return ColumnBase::upper_bound(*this, value);
1515 }
1516
1517 // For a *sorted* Column, return first element E for which E >= target or return -1 if none
1518 template <class T>
1519 size_t Column<T>::find_gte(T target, size_t start) const
1520 {
1521     // fixme: slow reference implementation. See Array::find_gte for faster version
1522     size_t ref = 0;
1523     size_t idx;
1524     for (idx = start; idx < size(); ++idx) {
1525         if (get(idx) >= target) {
1526             ref = idx;
1527             break;
1528         }
1529     }
1530     if (idx == size())
1531         ref = not_found;
1532
1533     return ref;
1534 }
1535
1536
1537 template <class T>
1538 bool Column<T>::compare(const Column<T>& c) const noexcept
1539 {
1540     size_t n = size();
1541     if (c.size() != n)
1542         return false;
1543     for (size_t i = 0; i < n; ++i) {
1544         bool left_is_null = is_null(i);
1545         bool right_is_null = c.is_null(i);
1546         if (left_is_null != right_is_null) {
1547             return false;
1548         }
1549         if (!left_is_null) {
1550             if (get(i) != c.get(i))
1551                 return false;
1552         }
1553     }
1554     return true;
1555 }
1556
1557 template <class T>
1558 int Column<T>::compare_values(size_t row1, size_t row2) const noexcept
1559 {
1560     return ColumnBase::compare_values(this, row1, row2);
1561 }
1562
1563 template <class T>
1564 class Column<T>::CreateHandler : public ColumnBase::CreateHandler {
1565 public:
1566     CreateHandler(Array::Type leaf_type, T value, Allocator& alloc)
1567         : m_value(value)
1568         , m_alloc(alloc)
1569         , m_leaf_type(leaf_type)
1570     {
1571     }
1572     ref_type create_leaf(size_t size) override
1573     {
1574         MemRef mem = BpTree<T>::create_leaf(m_leaf_type, size, m_value, m_alloc); // Throws
1575         return mem.get_ref();
1576     }
1577
1578 private:
1579     const T m_value;
1580     Allocator& m_alloc;
1581     Array::Type m_leaf_type;
1582 };
1583
1584 template <class T>
1585 ref_type Column<T>::create(Allocator& alloc, Array::Type leaf_type, size_t size, T value)
1586 {
1587     CreateHandler handler(leaf_type, std::move(value), alloc);
1588     return ColumnBase::create(alloc, size, handler);
1589 }
1590
1591 template <class T>
1592 ref_type Column<T>::write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream& out) const
1593 {
1594     return m_tree.write(slice_offset, slice_size, table_size, out);
1595 }
1596
1597 template <class T>
1598 void Column<T>::refresh_accessor_tree(size_t new_col_ndx, const Spec& spec)
1599 {
1600     m_tree.init_from_parent();
1601     ColumnBaseWithIndex::refresh_accessor_tree(new_col_ndx, spec);
1602 }
1603
1604 template <class T>
1605 void Column<T>::do_erase(size_t row_ndx, size_t num_rows_to_erase, bool is_last)
1606 {
1607     if (has_search_index()) {
1608         for (size_t i = num_rows_to_erase; i > 0; --i) {
1609             size_t row_ndx_2 = row_ndx + i - 1;
1610             m_search_index->erase<T>(row_ndx_2, is_last); // Throws
1611         }
1612     }
1613     for (size_t i = num_rows_to_erase; i > 0; --i) {
1614         size_t row_ndx_2 = row_ndx + i - 1;
1615         erase_without_updating_index(row_ndx_2, is_last); // Throws
1616     }
1617 }
1618
1619 template <class T>
1620 void Column<T>::verify() const
1621 {
1622 #ifdef REALM_DEBUG
1623     m_tree.verify();
1624 #endif
1625 }
1626
1627 // LCOV_EXCL_START
1628
1629 template <class T>
1630 void Column<T>::to_dot(std::ostream& out, StringData title) const
1631 {
1632 #ifdef REALM_DEBUG
1633     ref_type ref = get_root_array()->get_ref();
1634     out << "subgraph cluster_integer_column" << ref << " {" << std::endl;
1635     out << " label = \"Integer column";
1636     if (title.size() != 0)
1637         out << "\\n'" << title << "'";
1638     out << "\";" << std::endl;
1639     tree_to_dot(out);
1640     out << "}" << std::endl;
1641 #else
1642     static_cast<void>(out);
1643     static_cast<void>(title);
1644 #endif
1645 }
1646
1647 template <class T>
1648 void Column<T>::leaf_to_dot(MemRef leaf_mem, ArrayParent* parent, size_t ndx_in_parent, std::ostream& out) const
1649 {
1650 #ifdef REALM_DEBUG
1651     BpTree<T>::leaf_to_dot(leaf_mem, parent, ndx_in_parent, out, get_alloc());
1652 #else
1653     static_cast<void>(leaf_mem);
1654     static_cast<void>(parent);
1655     static_cast<void>(ndx_in_parent);
1656     static_cast<void>(out);
1657 #endif
1658 }
1659
1660 template <class T>
1661 void Column<T>::do_dump_node_structure(std::ostream& out, int level) const
1662 {
1663 #ifdef REALM_DEBUG
1664     dump_node_structure(*get_root_array(), out, level);
1665 #else
1666     static_cast<void>(out);
1667     static_cast<void>(level);
1668 #endif
1669 }
1670
1671 #ifdef REALM_DEBUG
1672
1673 template <class T>
1674 void Column<T>::tree_to_dot(std::ostream& out) const
1675 {
1676     ColumnBase::bptree_to_dot(get_root_array(), out);
1677 }
1678
1679
1680 template <class T>
1681 MemStats Column<T>::stats() const
1682 {
1683     MemStats mem_stats;
1684     get_root_array()->stats(mem_stats);
1685     return mem_stats;
1686 }
1687
1688 namespace _impl {
1689 void leaf_dumper(MemRef mem, Allocator& alloc, std::ostream& out, int level);
1690 }
1691
1692 template <class T>
1693 void Column<T>::dump_node_structure(const Array& root, std::ostream& out, int level)
1694 {
1695     root.dump_bptree_structure(out, level, &_impl::leaf_dumper);
1696 }
1697
1698 #endif
1699
1700 template <class T>
1701 std::pair<ref_type, size_t> Column<T>::get_to_dot_parent(size_t ndx_in_parent) const
1702 {
1703     auto root = get_root_array();
1704     if (root->is_inner_bptree_node()) {
1705         std::pair<MemRef, size_t> p = static_cast<const BpTreeNode*>(root)->get_bptree_leaf(ndx_in_parent);
1706         return std::make_pair(p.first.get_ref(), p.second);
1707     }
1708     else {
1709         return std::make_pair(root->get_ref(), ndx_in_parent);
1710     }
1711 }
1712
1713 // LCOV_EXCL_STOP ignore debug functions
1714
1715
1716 template <class ColumnDataType>
1717 ColumnRandIterator<ColumnDataType>::ColumnRandIterator(const Column<ColumnDataType>* src_col, size_t ndx)
1718     : m_col_ndx(ndx)
1719     , m_col(src_col)
1720 {
1721 }
1722
1723 template <class ColumnDataType>
1724 bool ColumnRandIterator<ColumnDataType>::operator==(const ColumnRandIterator<ColumnDataType>& rhs) const
1725 {
1726     return (m_col_ndx == rhs.m_col_ndx);
1727 }
1728
1729 template <class ColumnDataType>
1730 bool ColumnRandIterator<ColumnDataType>::operator!=(const ColumnRandIterator<ColumnDataType>& rhs) const
1731 {
1732     return !(*this == rhs);
1733 }
1734
1735 template <class ColumnDataType>
1736 bool ColumnRandIterator<ColumnDataType>::operator<(const ColumnRandIterator<ColumnDataType>& rhs) const
1737 {
1738     return m_col_ndx < rhs.m_col_ndx;
1739 }
1740
1741 template <class ColumnDataType>
1742 bool ColumnRandIterator<ColumnDataType>::operator>(const ColumnRandIterator<ColumnDataType>& rhs) const
1743 {
1744     return rhs < *this;
1745 }
1746
1747 template <class ColumnDataType>
1748 bool ColumnRandIterator<ColumnDataType>::operator<=(const ColumnRandIterator<ColumnDataType>& rhs) const
1749 {
1750     return !(rhs < *this);
1751 }
1752
1753 template <class ColumnDataType>
1754 bool ColumnRandIterator<ColumnDataType>::operator>=(const ColumnRandIterator<ColumnDataType>& rhs) const
1755 {
1756     return !(*this < rhs);
1757 }
1758
1759 template <class ColumnDataType>
1760 ColumnRandIterator<ColumnDataType>& ColumnRandIterator<ColumnDataType>::operator+=(ptrdiff_t movement)
1761 {
1762     m_col_ndx += movement;
1763     return (*this);
1764 }
1765
1766 template <class ColumnDataType>
1767 ColumnRandIterator<ColumnDataType>& ColumnRandIterator<ColumnDataType>::operator-=(ptrdiff_t movement)
1768 {
1769     m_col_ndx -= movement;
1770     return (*this);
1771 }
1772
1773 template <class ColumnDataType>
1774 ColumnRandIterator<ColumnDataType>& ColumnRandIterator<ColumnDataType>::operator++()
1775 {
1776     ++m_col_ndx;
1777     return (*this);
1778 }
1779
1780 template <class ColumnDataType>
1781 ColumnRandIterator<ColumnDataType>& ColumnRandIterator<ColumnDataType>::operator--()
1782 {
1783     --m_col_ndx;
1784     return (*this);
1785 }
1786
1787 template <class ColumnDataType>
1788 ColumnRandIterator<ColumnDataType> ColumnRandIterator<ColumnDataType>::operator++(int)
1789 {
1790     auto temp(*this);
1791     ++m_col_ndx;
1792     return temp;
1793 }
1794
1795 template <class ColumnDataType>
1796 ColumnRandIterator<ColumnDataType> ColumnRandIterator<ColumnDataType>::operator--(int)
1797 {
1798     auto temp(*this);
1799     --m_col_ndx;
1800     return temp;
1801 }
1802
1803 template <class ColumnDataType>
1804 ColumnRandIterator<ColumnDataType> ColumnRandIterator<ColumnDataType>::operator+(ptrdiff_t movement)
1805 {
1806     return ColumnRandIterator(m_col, m_col_ndx + movement);
1807 }
1808
1809 template <class ColumnDataType>
1810 ColumnRandIterator<ColumnDataType> ColumnRandIterator<ColumnDataType>::operator-(ptrdiff_t movement)
1811 {
1812     return ColumnRandIterator(m_col, m_col_ndx - movement);
1813 }
1814
1815 template <class ColumnDataType>
1816 ptrdiff_t ColumnRandIterator<ColumnDataType>::operator-(const ColumnRandIterator<ColumnDataType>& right) const
1817 {
1818     return m_col_ndx - right.m_col_ndx;
1819 }
1820
1821 template <class ColumnDataType>
1822 const ColumnDataType ColumnRandIterator<ColumnDataType>::operator*() const
1823 {
1824     return m_col->get(m_col_ndx);
1825 }
1826
1827 template <class ColumnDataType>
1828 const ColumnDataType ColumnRandIterator<ColumnDataType>::operator->() const
1829 {
1830     return m_col->get(m_col_ndx);
1831 }
1832
1833 template <class ColumnDataType>
1834 const ColumnDataType ColumnRandIterator<ColumnDataType>::operator[](ptrdiff_t offset) const
1835 {
1836     return m_col->get(m_col_ndx + offset);
1837 }
1838
1839 template <class ColumnDataType>
1840 size_t ColumnRandIterator<ColumnDataType>::get_col_ndx() const
1841 {
1842     return m_col_ndx;
1843 }
1844
1845 template <class ColumnDataType>
1846 std::ostream& operator<<(std::ostream& out, const ColumnRandIterator<ColumnDataType>& it)
1847 {
1848     out << "ColumnRandIterator at index: " << it.get_col_ndx();
1849     return out;
1850 }
1851
1852 } // namespace realm
1853
1854 #endif // REALM_COLUMN_HPP