From 8ccfc23efe3dfb9f9684820b79b48f93c937b9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Edelbo?= Date: Mon, 1 Jul 2024 16:39:24 +0200 Subject: [PATCH 1/4] Remove enum string feature --- CHANGELOG.md | 2 +- src/realm/array_string.cpp | 88 +----- src/realm/array_string.hpp | 14 +- src/realm/cluster.cpp | 53 +--- src/realm/cluster.hpp | 1 - src/realm/cluster_tree.cpp | 55 ---- src/realm/cluster_tree.hpp | 3 - src/realm/node.hpp | 5 - src/realm/obj.cpp | 39 +-- src/realm/obj.hpp | 2 - src/realm/query_engine.cpp | 6 +- src/realm/query_engine.hpp | 8 - src/realm/spec.cpp | 35 --- src/realm/spec.hpp | 6 - src/realm/table.cpp | 30 --- src/realm/table.hpp | 8 - test/expect_json.json | 432 +++++++++++++++++++++++++++++- test/expect_xjson.json | 15 -- test/expect_xjson_plus.json | 15 -- test/fuzz_group.cpp | 14 - test/realm-fuzzer/fuzz_engine.cpp | 3 - test/realm-fuzzer/fuzz_object.cpp | 14 - test/realm-fuzzer/fuzz_object.hpp | 1 - test/realm-fuzzer/util.hpp | 3 +- test/test_group.cpp | 47 ---- test/test_index_string.cpp | 106 ++------ test/test_json.cpp | 15 -- test/test_lang_bind_helper.cpp | 97 ------- test/test_links.cpp | 11 - test/test_query.cpp | 90 +------ test/test_query2.cpp | 44 +-- test/test_shared.cpp | 41 --- test/test_table.cpp | 248 +---------------- test/test_table_view.cpp | 40 --- test/test_transactions.cpp | 37 --- 35 files changed, 479 insertions(+), 1149 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e1ef2a9395..10ca5af2332 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ ----------- ### Internals -* None. +* Ability to enumerate a string column has been removed. ---------------------------------------------- diff --git a/src/realm/array_string.cpp b/src/realm/array_string.cpp index 72df74c524f..1eb2fdaa969 100644 --- a/src/realm/array_string.cpp +++ b/src/realm/array_string.cpp @@ -54,24 +54,9 @@ void ArrayString::init_from_mem(MemRef mem) noexcept else { auto arr = new (&m_storage) Array(m_alloc); arr->init_from_mem(mem); - // The context flag is used to indicate interned strings vs old enum strings - // (in conjunction with has_refs() == false) - if (arr->get_context_flag_from_header(arr->get_header())) { - // init for new interned strings (replacing old enum strings) - m_type = Type::interned_strings; - // consider if we want this invariant: REALM_ASSERT_DEBUG(m_string_interner); - } - else { - // init for old enum strings - m_string_enum_values = std::make_unique(m_alloc); - ArrayParent* p; - REALM_ASSERT(m_spec != nullptr); - REALM_ASSERT(m_col_ndx != realm::npos); - ref_type r = m_spec->get_enumkeys_ref(m_col_ndx, p); - m_string_enum_values->init_from_ref(r); - m_string_enum_values->set_parent(p, m_col_ndx); - m_type = Type::enum_strings; - } + // init for new interned strings + m_type = Type::interned_strings; + // consider if we want this invariant: REALM_ASSERT_DEBUG(m_string_interner); } } else { @@ -122,7 +107,6 @@ size_t ArrayString::size() const return static_cast(m_arr)->size(); case Type::big_strings: return static_cast(m_arr)->size(); - case Type::enum_strings: case Type::interned_strings: return static_cast(m_arr)->size(); } @@ -141,7 +125,6 @@ void ArrayString::add(StringData value) case Type::big_strings: static_cast(m_arr)->add_string(value); break; - case Type::enum_strings: case Type::interned_strings: { auto a = static_cast(m_arr); size_t ndx = a->size(); @@ -169,16 +152,6 @@ void ArrayString::set(size_t ndx, StringData value) static_cast(m_arr)->set(ndx, id); break; } - case Type::enum_strings: { - size_t sz = m_string_enum_values->size(); - size_t res = m_string_enum_values->find_first(value, 0, sz); - if (res == realm::not_found) { - m_string_enum_values->add(value); - res = sz; - } - static_cast(m_arr)->set(ndx, res); - break; - } } } @@ -194,11 +167,6 @@ void ArrayString::insert(size_t ndx, StringData value) case Type::big_strings: static_cast(m_arr)->insert_string(ndx, value); break; - case Type::enum_strings: { - static_cast(m_arr)->insert(ndx, 0); - set(ndx, value); - break; - } case Type::interned_strings: { static_cast(m_arr)->insert(ndx, 0); set(ndx, value); @@ -216,31 +184,6 @@ StringData ArrayString::get(size_t ndx) const return static_cast(m_arr)->get_string(ndx); case Type::big_strings: return static_cast(m_arr)->get_string(ndx); - case Type::enum_strings: { - size_t index = size_t(static_cast(m_arr)->get(ndx)); - return m_string_enum_values->get(index); - } - case Type::interned_strings: { - size_t id = size_t(static_cast(m_arr)->get(ndx)); - return m_string_interner->get(id); - } - } - return {}; -} - -StringData ArrayString::get_legacy(size_t ndx) const -{ - switch (m_type) { - case Type::small_strings: - return static_cast(m_arr)->get(ndx); - case Type::medium_strings: - return static_cast(m_arr)->get_string_legacy(ndx); - case Type::big_strings: - return static_cast(m_arr)->get_string(ndx); - case Type::enum_strings: { - size_t index = size_t(static_cast(m_arr)->get(ndx)); - return m_string_enum_values->get(index); - } case Type::interned_strings: { size_t id = size_t(static_cast(m_arr)->get(ndx)); return m_string_interner->get(id); @@ -263,10 +206,6 @@ bool ArrayString::is_null(size_t ndx) const return static_cast(m_arr)->is_null(ndx); case Type::big_strings: return static_cast(m_arr)->is_null(ndx); - case Type::enum_strings: { - size_t id = size_t(static_cast(m_arr)->get(ndx)); - return m_string_enum_values->is_null(id); - } case Type::interned_strings: { size_t id = size_t(static_cast(m_arr)->get(ndx)); return id == 0; @@ -288,7 +227,6 @@ void ArrayString::erase(size_t ndx) static_cast(m_arr)->erase(ndx); break; case Type::interned_strings: - case Type::enum_strings: static_cast(m_arr)->erase(ndx); break; } @@ -311,10 +249,6 @@ void ArrayString::move(ArrayString& dst, size_t ndx) case Type::big_strings: static_cast(m_arr)->truncate(ndx); break; - case Type::enum_strings: - // this operation will never be called for enumerated columns - REALM_UNREACHABLE(); - break; case Type::interned_strings: m_arr->truncate(ndx); break; @@ -333,7 +267,6 @@ void ArrayString::clear() case Type::big_strings: static_cast(m_arr)->clear(); break; - case Type::enum_strings: case Type::interned_strings: static_cast(m_arr)->clear(); break; @@ -355,14 +288,6 @@ size_t ArrayString::find_first(StringData value, size_t begin, size_t end) const return static_cast(m_arr)->find_first(as_binary, true, begin, end); break; } - case Type::enum_strings: { - size_t sz = m_string_enum_values->size(); - size_t res = m_string_enum_values->find_first(value, 0, sz); - if (res != realm::not_found) { - return static_cast(m_arr)->find_first(res, begin, end); - } - break; - } case Type::interned_strings: { // we need a way to avoid this lookup for each leaf array. The lookup must appear // higher up the call stack and passed down. @@ -420,8 +345,6 @@ size_t ArrayString::lower_bound(StringData value) return lower_bound_string(static_cast(m_arr), value); case Type::big_strings: return lower_bound_string(static_cast(m_arr), value); - case Type::enum_strings: - break; case Type::interned_strings: REALM_UNREACHABLE(); break; @@ -434,9 +357,6 @@ ArrayString::Type ArrayString::upgrade_leaf(size_t value_size) if (m_type == Type::big_strings) return Type::big_strings; - if (m_type == Type::enum_strings) - return Type::enum_strings; - if (m_type == Type::interned_strings) return Type::interned_strings; @@ -529,7 +449,6 @@ void ArrayString::verify() const case Type::big_strings: static_cast(m_arr)->verify(); break; - case Type::enum_strings: case Type::interned_strings: static_cast(m_arr)->verify(); break; @@ -567,7 +486,6 @@ ref_type ArrayString::typed_write(ref_type ref, _impl::ArrayWriterBase& out, All leaf.destroy_deep(true); } else { - // whether it's the old enum strings or the new interned strings, // just write out the array using integer leaf compression ret_val = leaf.write(out, false, out.only_modified, out.compress); } diff --git a/src/realm/array_string.hpp b/src/realm/array_string.hpp index 6c8400c4055..cdf8ccededa 100644 --- a/src/realm/array_string.hpp +++ b/src/realm/array_string.hpp @@ -74,15 +74,6 @@ class ArrayString : public ArrayPayload { { m_string_interner = string_interner; } - bool need_spec() const override - { - return true; - } - void set_spec(Spec* spec, size_t col_ndx) const override - { - m_spec = spec; - m_col_ndx = col_ndx; - } void update_parent() { @@ -108,7 +99,6 @@ class ArrayString : public ArrayPayload { } void insert(size_t ndx, StringData value); StringData get(size_t ndx) const; - StringData get_legacy(size_t ndx) const; Mixed get_any(size_t ndx) const override; bool is_null(size_t ndx) const; void erase(size_t ndx); @@ -137,7 +127,7 @@ class ArrayString : public ArrayPayload { static constexpr size_t storage_size = std::max({sizeof(ArrayStringShort), sizeof(ArraySmallBlobs), sizeof(ArrayBigBlobs), sizeof(Array)}); - enum class Type { small_strings, medium_strings, big_strings, enum_strings, interned_strings }; + enum class Type { small_strings, medium_strings, big_strings, interned_strings }; Type m_type = Type::small_strings; @@ -145,8 +135,6 @@ class ArrayString : public ArrayPayload { alignas(storage_alignment) std::byte m_storage[storage_size]; Array* m_arr; bool m_nullable = true; - mutable Spec* m_spec = nullptr; - mutable size_t m_col_ndx = realm::npos; std::unique_ptr m_string_enum_values; mutable StringInterner* m_string_interner = nullptr; diff --git a/src/realm/cluster.cpp b/src/realm/cluster.cpp index 6edec52a9e2..28b2e1a7a9d 100644 --- a/src/realm/cluster.cpp +++ b/src/realm/cluster.cpp @@ -154,12 +154,7 @@ void Cluster::create() do_create(col_key); break; case col_type_String: { - if (m_tree_top.is_string_enum_type(col_ndx)) { - do_create(col_key); - } - else { - do_create(col_key); - } + do_create(col_key); break; } case col_type_Binary: @@ -267,17 +262,6 @@ inline void Cluster::set_string_interner(ArrayMixed& arr, ColKey col_key) const m_tree_top.set_string_interner(arr, col_key); } -template -inline void Cluster::set_spec(T&, ColKey::Idx) const -{ -} - -template <> -inline void Cluster::set_spec(ArrayString& arr, ColKey::Idx col_ndx) const -{ - m_tree_top.set_spec(arr, col_ndx); -} - template inline void Cluster::do_insert_row(size_t ndx, ColKey col, Mixed init_val, bool nullable) { @@ -286,7 +270,6 @@ inline void Cluster::do_insert_row(size_t ndx, ColKey col, Mixed init_val, bool T arr(m_alloc); auto col_ndx = col.get_index(); arr.set_parent(this, col_ndx.val + s_first_col_index); - set_spec(arr, col_ndx); set_string_interner(arr, col); arr.init_from_parent(); if (init_val.is_null()) { @@ -506,13 +489,9 @@ void Cluster::move(size_t ndx, ClusterNode* new_node, int64_t offset) case col_type_Double: do_move(ndx, col_key, new_leaf); break; - case col_type_String: { - if (m_tree_top.is_string_enum_type(col_key.get_index())) - do_move(ndx, col_key, new_leaf); - else - do_move(ndx, col_key, new_leaf); + case col_type_String: + do_move(ndx, col_key, new_leaf); break; - } case col_type_Binary: do_move(ndx, col_key, new_leaf); break; @@ -780,7 +759,6 @@ inline void Cluster::do_erase(size_t ndx, ColKey col_key) auto col_ndx = col_key.get_index(); T values(m_alloc); values.set_parent(this, col_ndx.val + s_first_col_index); - set_spec(values, col_ndx); set_string_interner(values, col_key); values.init_from_parent(); if constexpr (std::is_same_v) { @@ -1047,26 +1025,6 @@ void Cluster::nullify_incoming_links(ObjKey key, CascadeState& state) m_tree_top.get_owning_table()->for_each_backlink_column(nullify_fwd_links); } -void Cluster::upgrade_string_to_enum(ColKey col_key, ArrayString& keys) -{ - auto col_ndx = col_key.get_index(); - Array indexes(m_alloc); - indexes.create(Array::type_Normal, false); - ArrayString values(m_alloc); - ref_type ref = Array::get_as_ref(col_ndx.val + s_first_col_index); - set_string_interner(values, col_key); - values.init_from_ref(ref); - size_t sz = values.size(); - for (size_t i = 0; i < sz; i++) { - auto v = values.get(i); - size_t pos = keys.lower_bound(v); - REALM_ASSERT_3(pos, !=, keys.size()); - indexes.add(pos); - } - Array::set(col_ndx.val + s_first_col_index, indexes.get_ref()); - Array::destroy_deep(ref, m_alloc); -} - void Cluster::init_leaf(ColKey col_key, ArrayPayload* leaf) const { auto col_ndx = col_key.get_index(); @@ -1079,9 +1037,6 @@ void Cluster::init_leaf(ColKey col_key, ArrayPayload* leaf) const if (leaf->need_string_interner()) { m_tree_top.set_string_interner(*leaf, col_key); } - if (leaf->need_spec()) { - m_tree_top.set_spec(*leaf, col_ndx); - } leaf->init_from_ref(ref); leaf->set_parent(const_cast(this), col_ndx.val + 1); } @@ -1097,7 +1052,6 @@ template void Cluster::verify(ref_type ref, size_t index, util::Optional& sz) const { ArrayType arr(get_alloc()); - set_spec(arr, ColKey::Idx{unsigned(index) - 1}); auto table = get_owning_table(); REALM_ASSERT(index <= table->m_leaf_ndx2colkey.size()); auto col_key = table->m_leaf_ndx2colkey[index - 1]; @@ -1439,7 +1393,6 @@ void Cluster::dump_objects(int64_t key_offset, std::string lead) const } case col_type_String: { ArrayString arr(m_alloc); - set_spec(arr, col.get_index()); set_string_interner(arr, col); ref_type ref = Array::get_as_ref(j); arr.init_from_ref(ref); diff --git a/src/realm/cluster.hpp b/src/realm/cluster.hpp index 365ad3a8634..64db02ae0d2 100644 --- a/src/realm/cluster.hpp +++ b/src/realm/cluster.hpp @@ -312,7 +312,6 @@ class Cluster : public ClusterNode { size_t get_ndx(ObjKey key, size_t ndx) const noexcept override; size_t erase(ObjKey k, CascadeState& state) override; void nullify_incoming_links(ObjKey key, CascadeState& state) override; - void upgrade_string_to_enum(ColKey col, ArrayString& keys); void init_leaf(ColKey col, ArrayPayload* leaf) const; void add_leaf(ColKey col, ref_type ref); diff --git a/src/realm/cluster_tree.cpp b/src/realm/cluster_tree.cpp index 5821a9f465b..99cf0e741b6 100644 --- a/src/realm/cluster_tree.cpp +++ b/src/realm/cluster_tree.cpp @@ -931,45 +931,6 @@ void ClusterTree::clear(CascadeState& state) m_size = 0; } -void ClusterTree::enumerate_string_column(ColKey col_key) -{ - Allocator& alloc = get_alloc(); - - ArrayString keys(alloc); - ArrayString leaf(alloc); - keys.create(); - - auto collect_strings = [col_key, &leaf, &keys](const Cluster* cluster) { - cluster->init_leaf(col_key, &leaf); - size_t sz = leaf.size(); - size_t key_size = keys.size(); - for (size_t i = 0; i < sz; i++) { - auto v = leaf.get(i); - size_t pos = keys.lower_bound(v); - if (pos == key_size || keys.get(pos) != v) { - keys.insert(pos, v); // Throws - key_size++; - } - } - - return IteratorControl::AdvanceToNext; - }; - - auto upgrade = [col_key, &keys](Cluster* cluster) { - cluster->upgrade_string_to_enum(col_key, keys); - }; - - // Populate 'keys' array - traverse(collect_strings); - - // Store key strings in spec - size_t spec_ndx = m_owner->colkey2spec_ndx(col_key); - const_cast(&m_owner->m_spec)->upgrade_string_to_enum(spec_ndx, keys.get_ref()); - - // Replace column in all clusters - update(upgrade); -} - void ClusterTree::replace_root(std::unique_ptr new_root) { if (new_root != m_root) { @@ -1144,16 +1105,6 @@ void ClusterTree::set_string_interner(ArrayPayload& arr, ColKey col_key) const } } -void ClusterTree::set_spec(ArrayPayload& arr, ColKey::Idx col_ndx) const -{ - // Check for owner. This function may be called in context of DictionaryClusterTree - // in which case m_owner is null (and spec never needed). - if (m_owner) { - auto spec_ndx = m_owner->leaf_ndx2spec_ndx(col_ndx); - arr.set_spec(&m_owner->m_spec, spec_ndx); - } -} - TableRef ClusterTree::get_table_ref() const { REALM_ASSERT(m_owner != nullptr); @@ -1183,12 +1134,6 @@ void ClusterTree::nullify_incoming_links(ObjKey obj_key, CascadeState& state) m_root->nullify_incoming_links(obj_key, state); } -bool ClusterTree::is_string_enum_type(ColKey::Idx col_ndx) const -{ - size_t spec_ndx = m_owner->leaf_ndx2spec_ndx(col_ndx); - return m_owner->m_spec.is_string_enum_type(spec_ndx); -} - void ClusterTree::remove_all_links(CascadeState& state) { Allocator& alloc = get_alloc(); diff --git a/src/realm/cluster_tree.hpp b/src/realm/cluster_tree.hpp index 15829f991bc..a0dad4b0805 100644 --- a/src/realm/cluster_tree.hpp +++ b/src/realm/cluster_tree.hpp @@ -153,7 +153,6 @@ class ClusterTree { } void clear(CascadeState&); - void enumerate_string_column(ColKey col_key); const Table* get_owning_table() const noexcept { @@ -180,7 +179,6 @@ class ClusterTree { // Visit all leaves and call the supplied function. The function can modify the leaf. void update(UpdateFunction func); - void set_spec(ArrayPayload& arr, ColKey::Idx col_ndx) const; void set_string_interner(ArrayPayload& arr, ColKey col_key) const; virtual std::unique_ptr get_root_from_parent(); @@ -225,7 +223,6 @@ class ClusterTree { std::unique_ptr create_root_from_parent(ArrayParent* parent, size_t ndx_in_parent); std::unique_ptr get_node(ArrayParent* parent, size_t ndx_in_parent) const; TableRef get_table_ref() const; - bool is_string_enum_type(ColKey::Idx col_ndx) const; void remove_all_links(CascadeState&); }; diff --git a/src/realm/node.hpp b/src/realm/node.hpp index 9b684f25246..57630f4812a 100644 --- a/src/realm/node.hpp +++ b/src/realm/node.hpp @@ -363,11 +363,6 @@ class ArrayPayload { return false; } virtual void set_string_interner(StringInterner*) const {} - virtual bool need_spec() const - { - return false; - } - virtual void set_spec(Spec*, size_t) const {} static ref_type typed_write(ref_type ref, _impl::ArrayWriterBase& out, Allocator& alloc); }; diff --git a/src/realm/obj.cpp b/src/realm/obj.cpp index 3f3e23b03bf..b07fb7cb059 100644 --- a/src/realm/obj.cpp +++ b/src/realm/obj.cpp @@ -608,22 +608,11 @@ StringData Obj::_get(ColKey::Idx col_ndx) const } ref_type ref = to_ref(Array::get(m_mem.get_addr(), col_ndx.val + 1)); - auto spec_ndx = m_table->leaf_ndx2spec_ndx(col_ndx); - auto& spec = get_spec(); - if (spec.is_string_enum_type(spec_ndx)) { - ArrayString values(get_alloc()); - values.set_spec(const_cast(&spec), spec_ndx); - values.init_from_ref(ref); - - return values.get(m_row_ndx); - } - else { - ArrayString values(get_alloc()); - auto col_key = m_table->leaf_ndx2colkey(col_ndx); - values.set_string_interner(m_table->get_string_interner(col_key)); - values.init_from_ref(ref); - return values.get(m_row_ndx); - } + ArrayString values(get_alloc()); + auto col_key = m_table->leaf_ndx2colkey(col_ndx); + values.set_string_interner(m_table->get_string_interner(col_key)); + values.init_from_ref(ref); + return values.get(m_row_ndx); } template <> @@ -750,7 +739,6 @@ inline bool Obj::do_is_null(ColKey::Idx col_ndx) const REALM_ASSERT(false); // Don't come here, you're falling from a cliff.... ArrayString values(get_alloc()); ref_type ref = to_ref(Array::get(m_mem.get_addr(), col_ndx.val + 1)); - values.set_spec(const_cast(&get_spec()), m_table->leaf_ndx2spec_ndx(col_ndx)); // TODO: Set string interner if needed // values.set_string_interner(m_table->get_string_interner(col_key)); values.init_from_ref(ref); @@ -780,7 +768,6 @@ bool Obj::is_null(ColKey col_key) const case col_type_String: { ArrayString values(get_alloc()); ref_type ref = to_ref(Array::get(m_mem.get_addr(), col_ndx.val + 1)); - values.set_spec(const_cast(&get_spec()), m_table->leaf_ndx2spec_ndx(col_ndx)); // TODO: Set string interner if needed values.set_string_interner(m_table->get_string_interner(col_key)); values.init_from_ref(ref); @@ -1189,19 +1176,6 @@ inline void Obj::set_string_interner(ArrayMixed& values, ColKey col_key) values.set_string_interner(m_table->get_string_interner(col_key)); } -// helper functions for filtering out calls to set_spec() -template -inline void Obj::set_spec(T&, ColKey) -{ -} -template <> -inline void Obj::set_spec(ArrayString& values, ColKey col_key) -{ - size_t spec_ndx = m_table->colkey2spec_ndx(col_key); - Spec* spec = const_cast(&get_spec()); - values.set_spec(spec, spec_ndx); -} - template <> Obj& Obj::set(ColKey col_key, Mixed value, bool is_default) { @@ -1722,7 +1696,6 @@ Obj& Obj::set(ColKey col_key, T value, bool is_default) using LeafType = typename ColumnTypeTraits::cluster_leaf_type; LeafType values(alloc); values.set_parent(&fields, col_ndx.val + 1); - set_spec(values, col_key); set_string_interner(values, col_key); values.init_from_parent(); values.set(m_row_ndx, value); @@ -2326,7 +2299,6 @@ template <> inline void Obj::do_set_null(ColKey col_key) { ColKey::Idx col_ndx = col_key.get_index(); - size_t spec_ndx = m_table->leaf_ndx2spec_ndx(col_ndx); Allocator& alloc = get_alloc(); alloc.bump_content_version(); Array fallback(alloc); @@ -2334,7 +2306,6 @@ inline void Obj::do_set_null(ColKey col_key) ArrayString values(alloc); values.set_parent(&fields, col_ndx.val + 1); - values.set_spec(const_cast(&get_spec()), spec_ndx); values.set_string_interner(m_table->get_string_interner(col_key)); values.init_from_parent(); values.set_null(m_row_ndx); diff --git a/src/realm/obj.hpp b/src/realm/obj.hpp index 8711e590dac..cffc1b56a70 100644 --- a/src/realm/obj.hpp +++ b/src/realm/obj.hpp @@ -391,8 +391,6 @@ class Obj { bool remove_one_backlink(ColKey backlink_col, ObjKey origin_key); void nullify_link(ColKey origin_col, ObjLink target_key) &&; template - inline void set_spec(T&, ColKey); - template inline void set_string_interner(T&, ColKey); template inline void nullify_single_link(ColKey col, ValueType target); diff --git a/src/realm/query_engine.cpp b/src/realm/query_engine.cpp index 7f303b23dac..ec24d5623dd 100644 --- a/src/realm/query_engine.cpp +++ b/src/realm/query_engine.cpp @@ -272,10 +272,7 @@ void StringNodeEqualBase::init(bool will_query_ranges) StringNodeBase::init(will_query_ranges); const bool uses_index = has_search_index(); - if (m_is_string_enum) { - m_dT = 1.0; - } - else if (uses_index) { + if (uses_index) { m_dT = 0.0; } else { @@ -516,7 +513,6 @@ StringNodeFulltext::StringNodeFulltext(StringData v, ColKey column, std::unique_ void StringNodeFulltext::table_changed() { - StringNodeEqualBase::table_changed(); m_link_map->set_base_table(m_table); } diff --git a/src/realm/query_engine.hpp b/src/realm/query_engine.hpp index 94cc9612a48..3a428c04d4d 100644 --- a/src/realm/query_engine.hpp +++ b/src/realm/query_engine.hpp @@ -1647,11 +1647,6 @@ class StringNodeBase : public ParentNode { m_dT = 10.0; } - void table_changed() override - { - m_is_string_enum = m_table.unchecked_ptr()->is_enumerated(m_condition_column_key); - } - void cluster_changed() override { m_leaf.emplace(m_table.unchecked_ptr()->get_alloc()); @@ -1678,7 +1673,6 @@ class StringNodeBase : public ParentNode { : ParentNode(from) , m_value(from.m_value) , m_string_value(m_value) - , m_is_string_enum(from.m_is_string_enum) { } @@ -1694,8 +1688,6 @@ class StringNodeBase : public ParentNode { std::optional m_leaf; StringData m_string_value; - bool m_is_string_enum = false; - size_t m_end_s = 0; size_t m_leaf_start = 0; size_t m_leaf_end = 0; diff --git a/src/realm/spec.cpp b/src/realm/spec.cpp index b2746f3c1c2..19fca5956b4 100644 --- a/src/realm/spec.cpp +++ b/src/realm/spec.cpp @@ -216,13 +216,6 @@ void Spec::erase_column(size_t column_ndx) REALM_ASSERT(column_ndx < m_types.size()); if (ColumnType(int(m_types.get(column_ndx))) != col_type_BackLink) { - if (is_string_enum_type(column_ndx)) { - // Enum columns do also have a separate key list - ref_type keys_ref = m_enumkeys.get_as_ref(column_ndx); - Array::destroy_deep(keys_ref, m_top.get_alloc()); - m_enumkeys.set(column_ndx, 0); - } - // Remove this column from the enum keys lookup and clean it up if it's now empty if (m_enumkeys.is_attached()) { m_enumkeys.erase(column_ndx); // Throws @@ -250,34 +243,6 @@ void Spec::erase_column(size_t column_ndx) update_internals(); } -void Spec::upgrade_string_to_enum(size_t column_ndx, ref_type keys_ref) -{ - REALM_ASSERT(get_column_type(column_ndx) == col_type_String); - - // Create the enumkeys list if needed - if (!m_enumkeys.is_attached()) { - m_enumkeys.create(Array::type_HasRefs, false, m_num_public_columns); - m_top.set(4, m_enumkeys.get_ref()); - m_enumkeys.set_parent(&m_top, 4); - } - - // Insert the new key list - m_enumkeys.set(column_ndx, keys_ref); -} - -bool Spec::is_string_enum_type(size_t column_ndx) const noexcept -{ - return m_enumkeys.is_attached() ? (m_enumkeys.get(column_ndx) != 0) : false; -} - -ref_type Spec::get_enumkeys_ref(size_t column_ndx, ArrayParent*& keys_parent) noexcept -{ - // We also need to return parent info - keys_parent = &m_enumkeys; - - return m_enumkeys.get_as_ref(column_ndx); -} - namespace { template diff --git a/src/realm/spec.hpp b/src/realm/spec.hpp index d1a17072f67..f361c61e9ef 100644 --- a/src/realm/spec.hpp +++ b/src/realm/spec.hpp @@ -65,12 +65,6 @@ class Spec { void set_dictionary_key_type(size_t column_ndx, DataType key_type); DataType get_dictionary_key_type(size_t column_ndx) const; - // Auto Enumerated string columns - void upgrade_string_to_enum(size_t column_ndx, ref_type keys_ref); - size_t _get_enumkeys_ndx(size_t column_ndx) const noexcept; - bool is_string_enum_type(size_t column_ndx) const noexcept; - ref_type get_enumkeys_ref(size_t column_ndx, ArrayParent*& keys_parent) noexcept; - //@{ /// Compare two table specs for equality. bool operator==(const Spec&) const noexcept; diff --git a/src/realm/table.cpp b/src/realm/table.cpp index be78abe7122..56c34c999f4 100644 --- a/src/realm/table.cpp +++ b/src/realm/table.cpp @@ -991,36 +991,6 @@ void Table::remove_search_index(ColKey col_key) m_spec.set_column_attr(spec_ndx, attr); // Throws } -void Table::enumerate_string_column(ColKey col_key) -{ - check_column(col_key); - size_t column_ndx = colkey2spec_ndx(col_key); - ColumnType type = col_key.get_type(); - if (type == col_type_String && !col_key.is_collection() && !m_spec.is_string_enum_type(column_ndx)) { - m_clusters.enumerate_string_column(col_key); - } -} - -bool Table::is_enumerated(ColKey col_key) const noexcept -{ - size_t col_ndx = colkey2spec_ndx(col_key); - return m_spec.is_string_enum_type(col_ndx); -} - -size_t Table::get_num_unique_values(ColKey col_key) const -{ - if (!is_enumerated(col_key)) - return 0; - - ArrayParent* parent; - ref_type ref = const_cast(m_spec).get_enumkeys_ref(colkey2spec_ndx(col_key), parent); - BPlusTree col(get_alloc()); - col.init_from_ref(ref); - - return col.size(); -} - - void Table::erase_root_column(ColKey col_key) { ColumnType col_type = col_key.get_type(); diff --git a/src/realm/table.hpp b/src/realm/table.hpp index 3635d265835..fd6e72c6bde 100644 --- a/src/realm/table.hpp +++ b/src/realm/table.hpp @@ -248,18 +248,10 @@ class Table { } void remove_search_index(ColKey col_key); - void enumerate_string_column(ColKey col_key); - bool is_enumerated(ColKey col_key) const noexcept; bool contains_unique_values(ColKey col_key) const; //@} - /// If the specified column is optimized to store only unique values, then - /// this function returns the number of unique values currently - /// stored. Otherwise it returns zero. This function is mainly intended for - /// debugging purposes. - size_t get_num_unique_values(ColKey col_key) const; - template Columns column(ColKey col_key, util::Optional = util::none) const; template diff --git a/test/expect_json.json b/test/expect_json.json index 4f4d0e227c3..5929348e35c 100644 --- a/test/expect_json.json +++ b/test/expect_json.json @@ -1 +1,431 @@ -[{"_key":0,"int":0,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string0","string_long":"string0 very long string.........","string_big_blobs":"string0 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum1","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[],"strings":[],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":1,"int":-1,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string1","string_long":"string1 very long string.........","string_big_blobs":"","string_enum":"enum2","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123],"strings":["sub_-123"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":2,"int":2,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string2","string_long":"string2 very long string.........","string_big_blobs":"string2 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum3","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,2345],"strings":["sub_-123","sub_2345"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":3,"int":-3,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string3","string_long":"string3 very long string.........","string_big_blobs":"","string_enum":"enum1","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,-3825,-7527],"strings":["sub_-123","sub_-3825","sub_-7527"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":4,"int":4,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string4","string_long":"string4 very long string.........","string_big_blobs":"string4 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum2","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,4813,9749,14685],"strings":["sub_-123","sub_4813","sub_9749","sub_14685"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":5,"int":-5,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string5","string_long":"string5 very long string.........","string_big_blobs":"","string_enum":"enum3","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[],"strings":[],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":6,"int":6,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string6","string_long":"string6 very long string.........","string_big_blobs":"string6 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum1","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123],"strings":["sub_-123"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":7,"int":-7,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string7","string_long":"string7 very long string.........","string_big_blobs":"","string_enum":"enum2","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,-8761],"strings":["sub_-123","sub_-8761"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":8,"int":8,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string8","string_long":"string8 very long string.........","string_big_blobs":"string8 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum3","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,9749,19621],"strings":["sub_-123","sub_9749","sub_19621"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":9,"int":-9,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string9","string_long":"string9 very long string.........","string_big_blobs":"","string_enum":"enum1","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,-11229,-22335,-33441],"strings":["sub_-123","sub_-11229","sub_-22335","sub_-33441"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":10,"int":10,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string10","string_long":"string10 very long string.........","string_big_blobs":"string10 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum2","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[],"strings":[],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":11,"int":-11,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string11","string_long":"string11 very long string.........","string_big_blobs":"","string_enum":"enum3","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123],"strings":["sub_-123"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":12,"int":12,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string12","string_long":"string12 very long string.........","string_big_blobs":"string12 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum1","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,14685],"strings":["sub_-123","sub_14685"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":13,"int":-13,"bool":true,"date":"1970-01-01 03:25:45","float":-1.2345600e+02,"double":-9.8765432099999998e+03,"string":"string13","string_long":"string13 very long string.........","string_big_blobs":"","string_enum":"enum2","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,-16165,-32207],"strings":["sub_-123","sub_-16165","sub_-32207"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"},{"_key":14,"int":14,"bool":false,"date":"1970-01-01 03:25:45","float":1.2345600e+02,"double":9.8765432099999998e+03,"string":"string14","string_long":"string14 very long string.........","string_big_blobs":"string14 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs","string_enum":"enum3","binary":"YmluYXJ5AA==","oid":"000000000000000000000000","decimal":"1.2345","integers":[-123,17153,34429,51705],"strings":["sub_-123","sub_17153","sub_34429","sub_51705"],"dictionary":{"a":2},"set":[123],"uuid":"00000000-0000-0000-0000-000000000000"}] \ No newline at end of file +[ + { + "_key": 0, + "int": 0, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string0", + "string_long": "string0 very long string.........", + "string_big_blobs": "string0 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [], + "strings": [], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 1, + "int": -1, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string1", + "string_long": "string1 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123 + ], + "strings": [ + "sub_-123" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 2, + "int": 2, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string2", + "string_long": "string2 very long string.........", + "string_big_blobs": "string2 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + 2345 + ], + "strings": [ + "sub_-123", + "sub_2345" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 3, + "int": -3, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string3", + "string_long": "string3 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + -3825, + -7527 + ], + "strings": [ + "sub_-123", + "sub_-3825", + "sub_-7527" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 4, + "int": 4, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string4", + "string_long": "string4 very long string.........", + "string_big_blobs": "string4 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + 4813, + 9749, + 14685 + ], + "strings": [ + "sub_-123", + "sub_4813", + "sub_9749", + "sub_14685" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 5, + "int": -5, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string5", + "string_long": "string5 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [], + "strings": [], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 6, + "int": 6, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string6", + "string_long": "string6 very long string.........", + "string_big_blobs": "string6 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123 + ], + "strings": [ + "sub_-123" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 7, + "int": -7, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string7", + "string_long": "string7 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + -8761 + ], + "strings": [ + "sub_-123", + "sub_-8761" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 8, + "int": 8, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string8", + "string_long": "string8 very long string.........", + "string_big_blobs": "string8 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + 9749, + 19621 + ], + "strings": [ + "sub_-123", + "sub_9749", + "sub_19621" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 9, + "int": -9, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string9", + "string_long": "string9 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + -11229, + -22335, + -33441 + ], + "strings": [ + "sub_-123", + "sub_-11229", + "sub_-22335", + "sub_-33441" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 10, + "int": 10, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string10", + "string_long": "string10 very long string.........", + "string_big_blobs": "string10 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [], + "strings": [], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 11, + "int": -11, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string11", + "string_long": "string11 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123 + ], + "strings": [ + "sub_-123" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 12, + "int": 12, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string12", + "string_long": "string12 very long string.........", + "string_big_blobs": "string12 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + 14685 + ], + "strings": [ + "sub_-123", + "sub_14685" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 13, + "int": -13, + "bool": true, + "date": "1970-01-01 03:25:45", + "float": -123.456, + "double": -9876.54321, + "string": "string13", + "string_long": "string13 very long string.........", + "string_big_blobs": "", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + -16165, + -32207 + ], + "strings": [ + "sub_-123", + "sub_-16165", + "sub_-32207" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + }, + { + "_key": 14, + "int": 14, + "bool": false, + "date": "1970-01-01 03:25:45", + "float": 123.456, + "double": 9876.54321, + "string": "string14", + "string_long": "string14 very long string.........", + "string_big_blobs": "string14 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", + "binary": "YmluYXJ5AA==", + "oid": "000000000000000000000000", + "decimal": "1.2345", + "integers": [ + -123, + 17153, + 34429, + 51705 + ], + "strings": [ + "sub_-123", + "sub_17153", + "sub_34429", + "sub_51705" + ], + "dictionary": { + "a": 2 + }, + "set": [ + 123 + ], + "uuid": "00000000-0000-0000-0000-000000000000" + } +] diff --git a/test/expect_xjson.json b/test/expect_xjson.json index 0a551ccc102..4f035b9c82d 100644 --- a/test/expect_xjson.json +++ b/test/expect_xjson.json @@ -18,7 +18,6 @@ "string": "string0", "string_long": "string0 very long string.........", "string_big_blobs": "string0 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -69,7 +68,6 @@ "string": "string1", "string_long": "string1 very long string.........", "string_big_blobs": "", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -126,7 +124,6 @@ "string": "string2", "string_long": "string2 very long string.........", "string_big_blobs": "string2 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -187,7 +184,6 @@ "string": "string3", "string_long": "string3 very long string.........", "string_big_blobs": "", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -252,7 +248,6 @@ "string": "string4", "string_long": "string4 very long string.........", "string_big_blobs": "string4 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -321,7 +316,6 @@ "string": "string5", "string_long": "string5 very long string.........", "string_big_blobs": "", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -372,7 +366,6 @@ "string": "string6", "string_long": "string6 very long string.........", "string_big_blobs": "string6 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -429,7 +422,6 @@ "string": "string7", "string_long": "string7 very long string.........", "string_big_blobs": "", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -490,7 +482,6 @@ "string": "string8", "string_long": "string8 very long string.........", "string_big_blobs": "string8 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -555,7 +546,6 @@ "string": "string9", "string_long": "string9 very long string.........", "string_big_blobs": "", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -624,7 +614,6 @@ "string": "string10", "string_long": "string10 very long string.........", "string_big_blobs": "string10 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -675,7 +664,6 @@ "string": "string11", "string_long": "string11 very long string.........", "string_big_blobs": "", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -732,7 +720,6 @@ "string": "string12", "string_long": "string12 very long string.........", "string_big_blobs": "string12 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -793,7 +780,6 @@ "string": "string13", "string_long": "string13 very long string.........", "string_big_blobs": "", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -858,7 +844,6 @@ "string": "string14", "string_long": "string14 very long string.........", "string_big_blobs": "string14 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", diff --git a/test/expect_xjson_plus.json b/test/expect_xjson_plus.json index 4b2f456835e..c0bcf5616e9 100644 --- a/test/expect_xjson_plus.json +++ b/test/expect_xjson_plus.json @@ -18,7 +18,6 @@ "string": "string0", "string_long": "string0 very long string.........", "string_big_blobs": "string0 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -73,7 +72,6 @@ "string": "string1", "string_long": "string1 very long string.........", "string_big_blobs": "", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -134,7 +132,6 @@ "string": "string2", "string_long": "string2 very long string.........", "string_big_blobs": "string2 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -199,7 +196,6 @@ "string": "string3", "string_long": "string3 very long string.........", "string_big_blobs": "", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -268,7 +264,6 @@ "string": "string4", "string_long": "string4 very long string.........", "string_big_blobs": "string4 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -341,7 +336,6 @@ "string": "string5", "string_long": "string5 very long string.........", "string_big_blobs": "", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -396,7 +390,6 @@ "string": "string6", "string_long": "string6 very long string.........", "string_big_blobs": "string6 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -457,7 +450,6 @@ "string": "string7", "string_long": "string7 very long string.........", "string_big_blobs": "", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -522,7 +514,6 @@ "string": "string8", "string_long": "string8 very long string.........", "string_big_blobs": "string8 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -591,7 +582,6 @@ "string": "string9", "string_long": "string9 very long string.........", "string_big_blobs": "", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -664,7 +654,6 @@ "string": "string10", "string_long": "string10 very long string.........", "string_big_blobs": "string10 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -719,7 +708,6 @@ "string": "string11", "string_long": "string11 very long string.........", "string_big_blobs": "", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -780,7 +768,6 @@ "string": "string12", "string_long": "string12 very long string.........", "string_big_blobs": "string12 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum1", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -845,7 +832,6 @@ "string": "string13", "string_long": "string13 very long string.........", "string_big_blobs": "", - "string_enum": "enum2", "binary": { "$binary": { "base64": "YmluYXJ5AA==", @@ -914,7 +900,6 @@ "string": "string14", "string_long": "string14 very long string.........", "string_big_blobs": "string14 very long string......... big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs big blobs", - "string_enum": "enum3", "binary": { "$binary": { "base64": "YmluYXJ5AA==", diff --git a/test/fuzz_group.cpp b/test/fuzz_group.cpp index f4c4e3c3c26..f19f995d98f 100644 --- a/test/fuzz_group.cpp +++ b/test/fuzz_group.cpp @@ -79,7 +79,6 @@ enum INS { CREATE_TABLE_VIEW, COMPACT, IS_NULL, - ENUMERATE_COLUMN, COUNT }; @@ -597,19 +596,6 @@ void parse_and_apply_instructions(std::string& in, const std::string& path, std: t->remove_object_recursive(key); } } - else if (instr == ENUMERATE_COLUMN && wt->size() > 0) { - TableKey table_key = wt->get_table_keys()[get_next(s) % wt->size()]; - TableRef t = wt->get_table(table_key); - auto all_col_keys = t->get_column_keys(); - if (!all_col_keys.empty()) { - size_t ndx = get_next(s) % all_col_keys.size(); - ColKey col = all_col_keys[ndx]; - if (log) { - *log << "wt->get_table(" << table_key << ")->enumerate_string_column(" << col << ");\n"; - } - wt->get_table(table_key)->enumerate_string_column(col); - } - } else if (instr == COMMIT) { if (log) { *log << "wt->commit_and_continue_as_read();\n"; diff --git a/test/realm-fuzzer/fuzz_engine.cpp b/test/realm-fuzzer/fuzz_engine.cpp index 896dbdceb4a..82951a6c5bf 100644 --- a/test/realm-fuzzer/fuzz_engine.cpp +++ b/test/realm-fuzzer/fuzz_engine.cpp @@ -151,9 +151,6 @@ void FuzzEngine::do_fuzz(FuzzConfigurator& cnf) else if (instr == Remove_Recursive && group.size() > 0) { fuzzer.remove_recursive(group, log, state); } - else if (instr == Enumerate_Column && group.size() > 0) { - fuzzer.enumerate_column(group, log, state); - } else if (instr == Commit) { fuzzer.commit(shared_realm, log); } diff --git a/test/realm-fuzzer/fuzz_object.cpp b/test/realm-fuzzer/fuzz_object.cpp index 80f28bb65dd..c1d66ea455a 100644 --- a/test/realm-fuzzer/fuzz_object.cpp +++ b/test/realm-fuzzer/fuzz_object.cpp @@ -324,20 +324,6 @@ void FuzzObject::remove_recursive(Group& group, FuzzLog& log, State& s) } } -void FuzzObject::enumerate_column(Group& group, FuzzLog& log, State& s) -{ - log << "FuzzObject::enumerate_column();\n"; - TableKey table_key = group.get_table_keys()[get_next_token(s) % group.size()]; - TableRef t = group.get_table(table_key); - auto all_col_keys = t->get_column_keys(); - if (!all_col_keys.empty()) { - size_t ndx = get_next_token(s) % all_col_keys.size(); - ColKey col = all_col_keys[ndx]; - log << "group.get_table(" << table_key << ")->enumerate_string_column(" << col << ");\n"; - group.get_table(table_key)->enumerate_string_column(col); - } -} - void FuzzObject::get_all_column_names(Group& group, FuzzLog& log) { log << "FuzzObject::get_all_column_names();\n"; diff --git a/test/realm-fuzzer/fuzz_object.hpp b/test/realm-fuzzer/fuzz_object.hpp index 469f76a109f..2fd31f79a7b 100644 --- a/test/realm-fuzzer/fuzz_object.hpp +++ b/test/realm-fuzzer/fuzz_object.hpp @@ -43,7 +43,6 @@ class FuzzObject { void set_obj(realm::Group& group, FuzzLog& log, State& s); void remove_obj(realm::Group& group, FuzzLog& log, State& s); void remove_recursive(realm::Group& group, FuzzLog& log, State& s); - void enumerate_column(realm::Group& group, FuzzLog& log, State& s); void get_all_column_names(realm::Group& group, FuzzLog& log); void commit(realm::SharedRealm shared_realm, FuzzLog& log); void rollback(realm::SharedRealm shared_realm, realm::Group& group, FuzzLog& log); diff --git a/test/realm-fuzzer/util.hpp b/test/realm-fuzzer/util.hpp index deb6946bdfb..1f1d6a5b754 100644 --- a/test/realm-fuzzer/util.hpp +++ b/test/realm-fuzzer/util.hpp @@ -52,8 +52,7 @@ enum Instruction { Create_Table_View = 20, Compact = 21, Is_Null = 22, - Enumerate_Column = 23, - Count = 24 + Count = 23 }; diff --git a/test/test_group.cpp b/test/test_group.cpp index c3c11c16ed5..530dfd59a6c 100644 --- a/test/test_group.cpp +++ b/test/test_group.cpp @@ -916,53 +916,6 @@ TEST(Group_Close) Group from_mem(buffer); } -TEST(Group_Serialize_Optimized) -{ - // Create group with one table - Group to_mem; - TableRef table = to_mem.add_table("test"); - test_table_add_columns(table); - - for (size_t i = 0; i < 5; ++i) { - table->create_object().set_all("abd", 1, true, int(Mon)); - table->create_object().set_all("eftg", 2, true, int(Tue)); - table->create_object().set_all("hijkl", 5, true, int(Wed)); - table->create_object().set_all("mnopqr", 8, true, int(Thu)); - table->create_object().set_all("stuvxyz", 9, true, int(Fri)); - } - - ColKey col_string = table->get_column_keys()[0]; - table->enumerate_string_column(col_string); - -#ifdef REALM_DEBUG - to_mem.verify(); -#endif - - // Serialize to memory (we now own the buffer) - BinaryData buffer = to_mem.write_to_mem(); - - // Load the table - Group from_mem(buffer); - TableRef t = from_mem.get_table("test"); - - CHECK_EQUAL(4, t->get_column_count()); - - // Verify that original values are there - CHECK(*table == *t); - - // Add a row with a known (but unique) value - auto k = table->create_object().set_all("search_target", 9, true, int(Fri)).get_key(); - - const auto res = table->find_first_string(col_string, "search_target"); - CHECK_EQUAL(k, res); - -#ifdef REALM_DEBUG - to_mem.verify(); - from_mem.verify(); -#endif -} - - TEST(Group_Serialize_All) { // Create group with one table diff --git a/test/test_index_string.cpp b/test/test_index_string.cpp index 83ed8c342ec..4a588cd0666 100644 --- a/test/test_index_string.cpp +++ b/test/test_index_string.cpp @@ -150,13 +150,10 @@ class column { std::vector m_keys; }; - column(bool nullable = false, bool enumerated = false) + column(bool nullable = false) : m_column(this) { m_col_key = m_table.add_column(ColumnTypeTraits::id, "values", nullable); - if (enumerated) { - m_table.enumerate_string_column(m_col_key); - } } ColumnTestType& get_column() { @@ -172,62 +169,24 @@ class column { class string_column : public column { public: string_column() - : column(false, false) + : column(false) { } static bool is_nullable() { return false; } - static bool is_enumerated() - { - return false; - } }; class nullable_string_column : public column { public: nullable_string_column() - : column(true, false) - { - } - static bool is_nullable() - { - return true; - } - static bool is_enumerated() - { - return false; - } -}; -class enum_column : public column { -public: - enum_column() - : column(false, true) - { - } - static bool is_nullable() - { - return false; - } - static bool is_enumerated() - { - return true; - } -}; -class nullable_enum_column : public column { -public: - nullable_enum_column() - : column(true, true) + : column(true) { } static bool is_nullable() { return true; } - static bool is_enumerated() - { - return true; - } }; // disable to avoid warnings about not being used - enable when tests @@ -300,7 +259,7 @@ TEST(StringIndex_NonIndexable) } } -TEST_TYPES(StringIndex_BuildIndex, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_BuildIndex, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -331,7 +290,7 @@ TEST_TYPES(StringIndex_BuildIndex, string_column, nullable_string_column, enum_c CHECK_EQUAL(6, r6.value); } -TEST_TYPES(StringIndex_DeleteAll, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_DeleteAll, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -379,7 +338,7 @@ TEST_TYPES(StringIndex_DeleteAll, string_column, nullable_string_column, enum_co CHECK(ndx.is_empty()); } -TEST_TYPES(StringIndex_Delete, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Delete, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -424,7 +383,7 @@ TEST_TYPES(StringIndex_Delete, string_column, nullable_string_column, enum_colum } -TEST_TYPES(StringIndex_ClearEmpty, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_ClearEmpty, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -437,7 +396,7 @@ TEST_TYPES(StringIndex_ClearEmpty, string_column, nullable_string_column, enum_c CHECK(ndx.is_empty()); } -TEST_TYPES(StringIndex_Clear, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Clear, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -482,7 +441,7 @@ TEST_TYPES(StringIndex_Clear, string_column, nullable_string_column, enum_column } -TEST_TYPES(StringIndex_Set, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Set, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -527,7 +486,7 @@ TEST_TYPES(StringIndex_Set, string_column, nullable_string_column, enum_column, CHECK_EQUAL(4, col.find_first(s6)); } -TEST_TYPES(StringIndex_Count, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Count, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -559,7 +518,7 @@ TEST_TYPES(StringIndex_Count, string_column, nullable_string_column, enum_column CHECK_EQUAL(4, c4); } -TEST_TYPES(StringIndex_Distinct, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Distinct, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -580,7 +539,7 @@ TEST_TYPES(StringIndex_Distinct, string_column, nullable_string_column, enum_col CHECK(ndx->has_duplicate_values()); } -TEST_TYPES(StringIndex_FindAllNoCopy, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_FindAllNoCopy, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -706,8 +665,7 @@ TEST(StringIndex_FindAllNoCopy2_IntNull) CHECK_EQUAL(results.payload, col.size() - 1); } -TEST_TYPES(StringIndex_FindAllNoCopyCommonPrefixStrings, string_column, nullable_string_column, enum_column, - nullable_enum_column) +TEST_TYPES(StringIndex_FindAllNoCopyCommonPrefixStrings, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -951,7 +909,7 @@ TEST_TYPES_IF(StringIndex_EmbeddedZeroesCombinations, TEST_DURATION > 1, string_ } // Tests for a bug with strings containing zeroes -TEST_TYPES(StringIndex_EmbeddedZeroes, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_EmbeddedZeroes, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col2 = test_resources.get_column(); @@ -982,10 +940,10 @@ TEST_TYPES(StringIndex_EmbeddedZeroes, string_column, nullable_string_column, en CHECK_EQUAL(f, null_key); } -TEST_TYPES(StringIndex_Null, nullable_string_column, nullable_enum_column) +TEST(StringIndex_Null) { - TEST_TYPE test_resources; - typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); + nullable_string_column test_resources; + auto& col = test_resources.get_column(); col.add(""); col.add(realm::null()); @@ -997,7 +955,7 @@ TEST_TYPES(StringIndex_Null, nullable_string_column, nullable_enum_column) } -TEST_TYPES(StringIndex_Zero_Crash, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Zero_Crash, string_column, nullable_string_column) { bool nullable = TEST_TYPE::is_nullable(); @@ -1010,9 +968,6 @@ TEST_TYPES(StringIndex_Zero_Crash, string_column, nullable_string_column, enum_c auto k2 = table.create_object().set(col, StringData("\0\0", 2)).get_key(); table.add_search_index(col); - if (TEST_TYPE::is_enumerated()) - table.enumerate_string_column(col); - ObjKey t; t = table.find_first_string(col, StringData("")); @@ -1154,7 +1109,7 @@ TEST(StringIndex_Integer_Increasing) } } -TEST_TYPES(StringIndex_Duplicate_Values, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Duplicate_Values, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1222,7 +1177,7 @@ TEST_TYPES(StringIndex_Duplicate_Values, string_column, nullable_string_column, CHECK(col.size() == 0); } -TEST_TYPES(StringIndex_MaxBytes, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_MaxBytes, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1267,7 +1222,7 @@ TEST_TYPES(StringIndex_MaxBytes, string_column, nullable_string_column, enum_col // for the characters at the end (they have an identical very // long prefix). This was causing a stack overflow because of // the recursive nature of the insert function. -TEST_TYPES(StringIndex_InsertLongPrefix, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_InsertLongPrefix, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1346,8 +1301,7 @@ TEST_TYPES(StringIndex_InsertLongPrefix, string_column, nullable_string_column, col.clear(); // calls recursive function Array::destroy_deep() } -TEST_TYPES(StringIndex_InsertLongPrefixAndQuery, string_column, nullable_string_column, enum_column, - nullable_enum_column) +TEST_TYPES(StringIndex_InsertLongPrefixAndQuery, string_column, nullable_string_column) { constexpr int half_node_size = REALM_MAX_BPNODE_SIZE / 2; bool nullable_column = TEST_TYPE::is_nullable(); @@ -1379,8 +1333,6 @@ TEST_TYPES(StringIndex_InsertLongPrefixAndQuery, string_column, nullable_string_ index->to_dot(o, ""); } */ - if (TEST_TYPE::is_enumerated()) - t->enumerate_string_column(col); auto ndx_a = t->where().equal(col, StringData(str_a)).find(); auto cnt = t->count_string(col, StringData(str_a)); @@ -1514,7 +1466,7 @@ void check_result_order(const std::vector& results, TestContext& test_co } // end anonymous namespace -TEST_TYPES(StringIndex_Insensitive, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Insensitive, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1681,7 +1633,7 @@ TEST_TYPES(StringIndex_Insensitive_Unicode, non_nullable, nullable) */ -TEST_TYPES(StringIndex_45, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_45, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1715,8 +1667,7 @@ std::string create_random_a_string(size_t max_len) // Excluded when run with valgrind because it takes a long time -TEST_TYPES_IF(StringIndex_Insensitive_Fuzz, TEST_DURATION > 1, string_column, nullable_string_column, enum_column, - nullable_enum_column) +TEST_TYPES_IF(StringIndex_Insensitive_Fuzz, TEST_DURATION > 1, string_column, nullable_string_column) { const size_t max_str_len = 9; const size_t iters = 3; @@ -1763,8 +1714,7 @@ TEST_TYPES_IF(StringIndex_Insensitive_Fuzz, TEST_DURATION > 1, string_column, nu // Exercise the StringIndex case insensitive search for strings with very long, common prefixes // to cover the special case code paths where different strings are stored in a list. -TEST_TYPES(StringIndex_Insensitive_VeryLongStrings, string_column, nullable_string_column, enum_column, - nullable_enum_column) +TEST_TYPES(StringIndex_Insensitive_VeryLongStrings, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1800,7 +1750,7 @@ TEST_TYPES(StringIndex_Insensitive_VeryLongStrings, string_column, nullable_stri // Bug with case insensitive search on numbers that gives duplicate results -TEST_TYPES(StringIndex_Insensitive_Numbers, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Insensitive_Numbers, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); @@ -1819,7 +1769,7 @@ TEST_TYPES(StringIndex_Insensitive_Numbers, string_column, nullable_string_colum } -TEST_TYPES(StringIndex_Rover, string_column, nullable_string_column, enum_column, nullable_enum_column) +TEST_TYPES(StringIndex_Rover, string_column, nullable_string_column) { TEST_TYPE test_resources; typename TEST_TYPE::ColumnTestType& col = test_resources.get_column(); diff --git a/test/test_json.cpp b/test/test_json.cpp index 39f61d2a981..c90aeea913a 100644 --- a/test/test_json.cpp +++ b/test/test_json.cpp @@ -93,7 +93,6 @@ void setup_multi_table(Table& table, size_t rows) table.add_column(type_String, "string"); // 5 table.add_column(type_String, "string_long"); // 6 ColKey col_string_big = table.add_column(type_String, "string_big_blobs"); // 7 - ColKey col_string_enum = table.add_column(type_String, "string_enum"); // 8 - becomes StringEnumColumn ColKey col_binary = table.add_column(type_Binary, "binary"); // 9 ColKey col_oid = table.add_column(type_ObjectId, "oid"); // 10 ColKey col_decimal = table.add_column(type_Decimal, "decimal"); // 11 @@ -128,17 +127,6 @@ void setup_multi_table(Table& table, size_t rows) obj.set(col_string_big, ""); break; } - switch (i % 3) { - case 0: - obj.set(col_string_enum, "enum1"); - break; - case 1: - obj.set(col_string_enum, "enum2"); - break; - case 2: - obj.set(col_string_enum, "enum3"); - break; - } obj.set(col_binary, BinaryData("binary", 7)); obj.set(col_oid, ObjectId()); obj.set(col_decimal, Decimal128("1.2345")); @@ -158,9 +146,6 @@ void setup_multi_table(Table& table, size_t rows) auto set = obj.get_set(col_set); set.insert(123); } - - // We also want a StringEnumColumn - table.enumerate_string_column(col_string_enum); } bool json_test(std::string json, std::string expected_file, bool generate) diff --git a/test/test_lang_bind_helper.cpp b/test/test_lang_bind_helper.cpp index 04467f781d0..925eb7ec852 100644 --- a/test/test_lang_bind_helper.cpp +++ b/test/test_lang_bind_helper.cpp @@ -989,54 +989,6 @@ TEST(LangBindHelper_AdvanceReadTransact_LinkColumnInNewTable) } -TEST(LangBindHelper_AdvanceReadTransact_EnumeratedStrings) -{ - SHARED_GROUP_TEST_PATH(path); - ShortCircuitHistory hist; - DBRef sg = DB::create(hist, path, DBOptions(crypt_key())); - ColKey c0, c1, c2; - - // Start a read transaction (to be repeatedly advanced) - auto rt = sg->start_read(); - CHECK_EQUAL(0, rt->size()); - - // Create 3 string columns, one primed for conversion to "unique string - // enumeration" representation - { - WriteTransaction wt(sg); - TableRef table_w = wt.add_table("t"); - c0 = table_w->add_column(type_String, "a"); - c1 = table_w->add_column(type_String, "b"); - c2 = table_w->add_column(type_String, "c"); - for (int i = 0; i < 1000; ++i) { - std::ostringstream out; - out << i; - std::string str = out.str(); - table_w->create_object(ObjKey{}, {{c0, str}, {c1, "foo"}, {c2, str}}); - } - wt.commit(); - } - rt->advance_read(); - rt->verify(); - ConstTableRef table = rt->get_table("t"); - CHECK_EQUAL(0, table->get_num_unique_values(c0)); - CHECK_EQUAL(0, table->get_num_unique_values(c1)); // Not yet "optimized" - CHECK_EQUAL(0, table->get_num_unique_values(c2)); - - // Optimize - { - WriteTransaction wt(sg); - TableRef table_w = wt.get_table("t"); - table_w->enumerate_string_column(c1); - wt.commit(); - } - rt->advance_read(); - rt->verify(); - CHECK_EQUAL(0, table->get_num_unique_values(c0)); - CHECK_NOT_EQUAL(0, table->get_num_unique_values(c1)); // Must be "optimized" now - CHECK_EQUAL(0, table->get_num_unique_values(c2)); -} - NONCONCURRENT_TEST_IF(LangBindHelper_AdvanceReadTransact_SearchIndex, testing_supports_spawn_process) { SHARED_GROUP_TEST_PATH(path); @@ -5593,28 +5545,6 @@ TEST(LangBindHelper_CopyOnWriteOverflow) } -TEST(LangBindHelper_RollbackOptimize) -{ - SHARED_GROUP_TEST_PATH(path); - const char* key = crypt_key(); - std::unique_ptr hist_w(make_in_realm_history()); - DBRef sg_w = DB::create(*hist_w, path, DBOptions(key)); - auto g = sg_w->start_write(); - - auto table = g->add_table("t0"); - auto col = table->add_column(type_String, "str_col_0", true); - g->commit_and_continue_as_read(); - g->verify(); - g->promote_to_write(); - g->verify(); - std::vector keys; - table->create_objects(198, keys); - table->enumerate_string_column(col); - g->rollback_and_continue_as_read(); - g->verify(); -} - - TEST(LangBindHelper_BinaryReallocOverMax) { SHARED_GROUP_TEST_PATH(path); @@ -5667,33 +5597,6 @@ TEST(LangBindHelper_OpenAsEncrypted) #endif -// Test case generated in [realm-core-4.0.4] on Mon Dec 18 13:33:24 2017. -// Adding 0 rows to a StringEnumColumn would add the default value to the keys -// but not the indexes creating an inconsistency. -TEST(LangBindHelper_EnumColumnAddZeroRows) -{ - SHARED_GROUP_TEST_PATH(path); - const char* key = nullptr; - std::unique_ptr hist(make_in_realm_history()); - DBRef sg = DB::create(*hist, path, DBOptions(key)); - auto g = sg->start_write(); - auto g_r = sg->start_read(); - auto table = g->add_table(""); - - auto col = table->add_column(DataType(2), "table", false); - table->enumerate_string_column(col); - g->commit_and_continue_as_read(); - g->verify(); - g->promote_to_write(); - g->verify(); - table->create_object(); - g->commit_and_continue_as_read(); - g_r->advance_read(); - g_r->verify(); - g->verify(); -} - - TEST(LangBindHelper_RemoveObject) { SHARED_GROUP_TEST_PATH(path); diff --git a/test/test_links.cpp b/test/test_links.cpp index 7561364089b..6e1eed71f47 100644 --- a/test/test_links.cpp +++ b/test/test_links.cpp @@ -752,17 +752,6 @@ TEST(ListList_Clear) CHECK_EQUAL(links2->size(), 0); } -TEST(Links_AddBacklinkToTableWithEnumColumns) -{ - Group g; - auto table = g.add_table("fshno"); - auto col = table->add_column(type_String, "strings", false); - table->create_object(); - table->add_column(*table, "link1"); - table->enumerate_string_column(col); - table->add_column(*table, "link2"); -} - TEST(Links_LinkList_Inserts) { Group group; diff --git a/test/test_query.cpp b/test/test_query.cpp index 313312f6ea7..c2d7215d35f 100644 --- a/test/test_query.cpp +++ b/test/test_query.cpp @@ -2124,15 +2124,12 @@ TEST_TYPES(Query_ListOfPrimitives_MinMax, int64_t, float, double, Decimal128, Ti validate_aggregate_results(test_context, table, col, value, max); } -TEST_TYPES(Query_StringIndexCommonPrefix, std::true_type, std::false_type) +TEST(Query_StringIndexCommonPrefix) { Group group; TableRef table = group.add_table("test"); auto col_str = table->add_column(type_String, "first"); table->add_search_index(col_str); - if (TEST_TYPE::value == true) { - table->enumerate_string_column(col_str); - } auto test_prefix_find = [&](std::string prefix) { std::string prefix_b = prefix + "b"; @@ -2822,8 +2819,6 @@ TEST(Query_Huge) for (size_t t = 0; t < 4; t++) { if (t == 1) { - tt.enumerate_string_column(col_str0); - tt.enumerate_string_column(col_str1); } else if (t == 2) { tt.add_search_index(col_str0); @@ -3007,8 +3002,6 @@ TEST_IF(Query_StrIndex3, TEST_DURATION > 0) for (size_t t = 0; t < vec.size(); t++) CHECK_EQUAL(vec[t], v.get_key(t)); - ttt.enumerate_string_column(col_str); - // Linear scan over enum, plus linear integer column scan v = ttt.where().equal(col_str, "AA").equal(col_int, 0).find_all(); CHECK_EQUAL(vec.size(), v.size()); @@ -3059,34 +3052,6 @@ TEST(Query_StrIndex2) CHECK_EQUAL(0, s); } -TEST(Query_StrEnum) -{ - Random random(random_int()); // Seed from slow global generator - Table ttt; - ttt.add_column(type_Int, "1"); - auto col_str = ttt.add_column(type_String, "2"); - - int aa; - int64_t s; - - for (int i = 0; i < 100; ++i) { - ttt.clear(); - aa = 0; - for (size_t t = 0; t < REALM_MAX_BPNODE_SIZE * 2; ++t) { - if (random.chance(1, 3)) { - ttt.create_object().set_all(1, "AA"); - ++aa; - } - else { - ttt.create_object().set_all(1, "BB"); - } - } - ttt.enumerate_string_column(col_str); - s = ttt.where().equal(col_str, "AA").count(); - CHECK_EQUAL(aa, s); - } -} - TEST(Query_StrIndex) { Random random(random_int()); // Seed from slow global generator @@ -3121,10 +3086,6 @@ TEST(Query_StrIndex) s = ttt.where().equal(str_col, "AA").count(); CHECK_EQUAL(aa, s); - ttt.enumerate_string_column(str_col); - s = ttt.where().equal(str_col, "AA").count(); - CHECK_EQUAL(aa, s); - ttt.add_search_index(str_col); s = ttt.where().equal(str_col, "AA").count(); CHECK_EQUAL(aa, s); @@ -3212,49 +3173,6 @@ TEST(Query_StrIndexUpdating) CHECK_EQUAL(tv_ins.size(), 0); } -TEST(Query_GA_Crash) -{ - GROUP_TEST_PATH(path); - Random random(random_int()); // Seed from slow global generator - { - Group g; - TableRef t = g.add_table("firstevents"); - auto col_str0 = t->add_column(type_String, "1"); - auto col_str1 = t->add_column(type_String, "2"); - auto col_str2 = t->add_column(type_String, "3"); - t->add_column(type_Int, "4"); - t->add_column(type_Int, "5"); - - for (size_t i = 0; i < 100; ++i) { - int64_t r1 = random.draw_int_mod(100); - int64_t r2 = random.draw_int_mod(100); - - t->create_object().set_all("10", "US", "1.0", r1, r2); - } - t->enumerate_string_column(col_str0); - t->enumerate_string_column(col_str1); - t->enumerate_string_column(col_str2); - g.write(path); - } - - Group g(path); - TableRef t = g.get_table("firstevents"); - auto col_str1 = t->get_column_key("2"); - - Query q = t->where().equal(col_str1, "US"); - - size_t c1 = 0; - for (size_t i = 0; i < 100; ++i) - c1 += t->count_string(col_str1, "US"); - - size_t c2 = 0; - for (size_t i = 0; i < 100; ++i) - c2 += q.count(); - - CHECK_EQUAL(c1, t->size() * 100); - CHECK_EQUAL(c1, c2); -} - TEST(Query_Float3) { Table t; @@ -3563,7 +3481,7 @@ TEST(Query_DoubleCoordinates) } -TEST_TYPES(Query_StrIndexed, std::true_type, std::false_type) +TEST(Query_StrIndexed) { Table ttt; auto col_int = ttt.add_column(type_Int, "1"); @@ -3578,10 +3496,6 @@ TEST_TYPES(Query_StrIndexed, std::true_type, std::false_type) ttt.create_object().set_all(4, "c"); } - if (TEST_TYPE::value == true) { - ttt.enumerate_string_column(col_str); - } - ttt.add_search_index(col_str); auto s = *ttt.where().equal(col_str, "a").sum(col_int); diff --git a/test/test_query2.cpp b/test/test_query2.cpp index b0dc4f75165..462fbcfc3dc 100644 --- a/test/test_query2.cpp +++ b/test/test_query2.cpp @@ -661,35 +661,6 @@ TEST(Query_Binary) } } -TEST(Query_Enums) -{ - Table table; - auto col_int = table.add_column(type_Int, "1"); - auto col_str = table.add_column(type_String, "2"); - - - for (size_t i = 0; i < 5; ++i) { - table.create_object().set_all(1, "abd"); - table.create_object().set_all(2, "eftg"); - table.create_object().set_all(5, "hijkl"); - table.create_object().set_all(8, "mnopqr"); - table.create_object().set_all(9, "stuvxyz"); - } - - table.enumerate_string_column(col_str); - - Query q1 = table.where().equal(col_str, "eftg"); - TableView tv1 = q1.find_all(); - - CHECK_EQUAL(5, tv1.size()); - CHECK_EQUAL(2, tv1[0].get(col_int)); - CHECK_EQUAL(2, tv1[1].get(col_int)); - CHECK_EQUAL(2, tv1[2].get(col_int)); - CHECK_EQUAL(2, tv1[3].get(col_int)); - CHECK_EQUAL(2, tv1[4].get(col_int)); -} - - TEST_TYPES(Query_CaseSensitivity, std::true_type, std::false_type) { constexpr bool nullable = TEST_TYPE::value; @@ -1422,29 +1393,16 @@ TEST(Query_NullStrings) TEST(Query_Nulls_Fuzzy) { - for (int attributes = 1; attributes < 5; attributes++) { + for (int attributes = 1; attributes < 3; attributes++) { Random random(random_int()); for (size_t t = 0; t < 10; t++) { Table table; auto col = table.add_column(type_String, "string", true); - if (attributes == 0) { - } if (attributes == 1) { table.add_search_index(col); } - else if (attributes == 2) { - table.enumerate_string_column(col); - } - else if (attributes == 3) { - table.add_search_index(col); - table.enumerate_string_column(col); - } - else if (attributes == 4) { - table.enumerate_string_column(col); - table.add_search_index(col); - } // map that is kept in sync with the column so that we can compare with it std::map v; diff --git a/test/test_shared.cpp b/test/test_shared.cpp index 8bbfc070a62..c8f75c47fed 100644 --- a/test/test_shared.cpp +++ b/test/test_shared.cpp @@ -2571,10 +2571,6 @@ TEST(Shared_MovingSearchIndex) obj.set(enum_col, "bar"); } table->get_object(obj_keys.back()).set(enum_col, "bar63"); - table->enumerate_string_column(enum_col); - CHECK_EQUAL(0, table->get_num_unique_values(int_col)); - CHECK_EQUAL(0, table->get_num_unique_values(str_col)); - CHECK_EQUAL(2, table->get_num_unique_values(enum_col)); table->add_search_index(int_col); table->add_search_index(str_col); @@ -2597,9 +2593,6 @@ TEST(Shared_MovingSearchIndex) CHECK(table->has_search_index(int_col)); CHECK(table->has_search_index(str_col)); CHECK(table->has_search_index(enum_col)); - CHECK_EQUAL(0, table->get_num_unique_values(int_col)); - CHECK_EQUAL(0, table->get_num_unique_values(str_col)); - CHECK_EQUAL(2, table->get_num_unique_values(enum_col)); CHECK_EQUAL(ObjKey(), table->find_first_int(int_col, 100)); CHECK_EQUAL(ObjKey(), table->find_first_string(str_col, "bad")); CHECK_EQUAL(ObjKey(), table->find_first_string(enum_col, "bad")); @@ -2613,9 +2606,6 @@ TEST(Shared_MovingSearchIndex) CHECK(table->has_search_index(int_col)); CHECK(table->has_search_index(str_col)); CHECK(table->has_search_index(enum_col)); - CHECK_EQUAL(0, table->get_num_unique_values(int_col)); - CHECK_EQUAL(0, table->get_num_unique_values(str_col)); - CHECK_EQUAL(2, table->get_num_unique_values(enum_col)); CHECK_EQUAL(ObjKey(), table->find_first_int(int_col, 100)); CHECK_EQUAL(ObjKey(), table->find_first_string(str_col, "bad")); CHECK_EQUAL(ObjKey(), table->find_first_string(enum_col, "bad")); @@ -2632,9 +2622,6 @@ TEST(Shared_MovingSearchIndex) CHECK(table->has_search_index(int_col)); CHECK(table->has_search_index(str_col)); CHECK(table->has_search_index(enum_col)); - CHECK_EQUAL(0, table->get_num_unique_values(int_col)); - CHECK_EQUAL(0, table->get_num_unique_values(str_col)); - CHECK_EQUAL(3, table->get_num_unique_values(enum_col)); CHECK_EQUAL(ObjKey(), table->find_first_int(int_col, 100)); CHECK_EQUAL(ObjKey(), table->find_first_string(str_col, "bad")); CHECK_EQUAL(ObjKey(), table->find_first_string(enum_col, "bad")); @@ -3632,34 +3619,6 @@ TEST(Shared_OpenAfterClose) db_w->close(); } -TEST(Shared_RemoveTableWithEnumAndLinkColumns) -{ - // Test case generated with fuzzer - SHARED_GROUP_TEST_PATH(path); - DBRef db_w = DB::create(path); - TableKey tk; - { - auto wt = db_w->start_write(); - wt->add_table("Table_2"); - wt->commit(); - } - { - auto wt = db_w->start_write(); - auto table = wt->get_table("Table_2"); - tk = table->get_key(); - auto col_key = table->add_column(DataType(2), "string_3", false); - table->enumerate_string_column(col_key); - table->add_column(*table, "link_5"); - table->add_search_index(col_key); - wt->commit(); - } - { - auto wt = db_w->start_write(); - wt->remove_table(tk); - wt->commit(); - } -} - TEST(Shared_GenerateObjectIdAfterRollback) { // Test case generated in [realm-core-6.0.0-alpha.0] on Mon Aug 13 14:43:06 2018. diff --git a/test/test_table.cpp b/test/test_table.cpp index 52e06fb2659..4029043e0e1 100644 --- a/test/test_table.cpp +++ b/test/test_table.cpp @@ -366,18 +366,6 @@ TEST(Table_DeleteCrash) table->remove_object(k1); } -TEST(Table_OptimizeCrash) -{ - // This will crash at the .add() method - Table ttt; - ttt.add_column(type_Int, "first"); - auto col = ttt.add_column(type_String, "second"); - ttt.enumerate_string_column(col); - ttt.add_search_index(col); - ttt.clear(); - ttt.create_object().set_all(1, "AA"); -} - TEST(Table_DateTimeMinMax) { Group g; @@ -1002,7 +990,6 @@ void setup_multi_table(Table& table, size_t rows, std::vector& keys, std auto string_col = table.add_column(type_String, "string"); // 4 auto string_long_col = table.add_column(type_String, "string_long"); // 5 auto string_big_col = table.add_column(type_String, "string_big_blobs"); // 6 - auto string_enum_col = table.add_column(type_String, "string_enum"); // 7 - becomes StringEnumColumn auto bin_col = table.add_column(type_Binary, "binary"); // 8 auto int_null_col = table.add_column(type_Int, "int_null", true); // 9, nullable = true column_keys.push_back(int_col); @@ -1012,7 +999,6 @@ void setup_multi_table(Table& table, size_t rows, std::vector& keys, std column_keys.push_back(string_col); column_keys.push_back(string_long_col); column_keys.push_back(string_big_col); - column_keys.push_back(string_enum_col); column_keys.push_back(bin_col); column_keys.push_back(int_null_col); @@ -1061,23 +1047,8 @@ void setup_multi_table(Table& table, size_t rows, std::vector& keys, std obj.set(string_big_col, StringData("")); break; } - // enum - switch (i % 3) { - case 0: - obj.set(string_enum_col, "enum1"); - break; - case 1: - obj.set(string_enum_col, "enum2"); - break; - case 2: - obj.set(string_enum_col, "enum3"); - break; - } obj.set(bin_col, BinaryData("binary", 7)); } - - // We also want a StringEnumColumn - table.enumerate_string_column(string_enum_col); } } // anonymous namespace @@ -1584,145 +1555,6 @@ TEST(Table_IndexInt) #endif } -TEST(Table_AutoEnumeration) -{ - Table table; - - auto col_int = table.add_column(type_Int, "first"); - auto col_str = table.add_column(type_String, "second"); - - for (size_t i = 0; i < 5; ++i) { - table.create_object().set_all(1, "abd"); - table.create_object().set_all(2, "eftg"); - table.create_object().set_all(5, "hijkl"); - table.create_object().set_all(8, "mnopqr"); - table.create_object().set_all(9, "stuvxyz"); - } - - table.enumerate_string_column(col_str); - - for (size_t i = 0; i < 5; ++i) { - const size_t n = i * 5; - CHECK_EQUAL(1, table.get_object(ObjKey(0 + n)).get(col_int)); - CHECK_EQUAL(2, table.get_object(ObjKey(1 + n)).get(col_int)); - CHECK_EQUAL(5, table.get_object(ObjKey(2 + n)).get(col_int)); - CHECK_EQUAL(8, table.get_object(ObjKey(3 + n)).get(col_int)); - CHECK_EQUAL(9, table.get_object(ObjKey(4 + n)).get(col_int)); - - CHECK_EQUAL("abd", table.get_object(ObjKey(0 + n)).get(col_str)); - CHECK_EQUAL("eftg", table.get_object(ObjKey(1 + n)).get(col_str)); - CHECK_EQUAL("hijkl", table.get_object(ObjKey(2 + n)).get(col_str)); - CHECK_EQUAL("mnopqr", table.get_object(ObjKey(3 + n)).get(col_str)); - CHECK_EQUAL("stuvxyz", table.get_object(ObjKey(4 + n)).get(col_str)); - } - - // Verify counts - const size_t count1 = table.count_string(col_str, "abd"); - const size_t count2 = table.count_string(col_str, "eftg"); - const size_t count3 = table.count_string(col_str, "hijkl"); - const size_t count4 = table.count_string(col_str, "mnopqr"); - const size_t count5 = table.count_string(col_str, "stuvxyz"); - CHECK_EQUAL(5, count1); - CHECK_EQUAL(5, count2); - CHECK_EQUAL(5, count3); - CHECK_EQUAL(5, count4); - CHECK_EQUAL(5, count5); - - ObjKey t = table.find_first_string(col_str, "eftg"); - CHECK_EQUAL(ObjKey(1), t); - - auto tv = table.find_all_string(col_str, "eftg"); - CHECK_EQUAL(5, tv.size()); - CHECK_EQUAL("eftg", tv.get_object(0).get(col_str)); - CHECK_EQUAL("eftg", tv.get_object(1).get(col_str)); - CHECK_EQUAL("eftg", tv.get_object(2).get(col_str)); - CHECK_EQUAL("eftg", tv.get_object(3).get(col_str)); - CHECK_EQUAL("eftg", tv.get_object(4).get(col_str)); - - Obj obj = table.create_object(); - CHECK_EQUAL(0, obj.get(col_int)); - CHECK_EQUAL("", obj.get(col_str)); -} - - -TEST(Table_AutoEnumerationOptimize) -{ - Table t; - auto col0 = t.add_column(type_String, "col1"); - auto col1 = t.add_column(type_String, "col2"); - auto col2 = t.add_column(type_String, "col3"); - auto col3 = t.add_column(type_String, "col4"); - - // Insert non-optimizable strings - std::string s; - std::vector keys; - t.create_objects(10, keys); - for (Obj o : t) { - o.set_all(s.c_str(), s.c_str(), s.c_str(), s.c_str()); - s += "x"; - } - - // AutoEnumerate in reverse order - for (Obj o : t) { - o.set(col3, "test"); - } - t.enumerate_string_column(col3); - for (Obj o : t) { - o.set(col2, "test"); - } - t.enumerate_string_column(col2); - for (Obj o : t) { - o.set(col1, "test"); - } - t.enumerate_string_column(col1); - for (Obj o : t) { - o.set(col0, "test"); - } - t.enumerate_string_column(col0); - - for (Obj o : t) { - CHECK_EQUAL("test", o.get(col0)); - CHECK_EQUAL("test", o.get(col1)); - CHECK_EQUAL("test", o.get(col2)); - CHECK_EQUAL("test", o.get(col3)); - } - -#ifdef REALM_DEBUG - t.verify(); -#endif -} - -TEST(Table_OptimizeCompare) -{ - Table t1, t2; - auto col_t1 = t1.add_column(type_String, "str"); - auto col_t2 = t2.add_column(type_String, "str"); - - std::vector keys_t1; - std::vector keys_t2; - t1.create_objects(100, keys_t1); - for (Obj o : t1) { - o.set(col_t1, "foo"); - } - t2.create_objects(100, keys_t2); - for (Obj o : t2) { - o.set(col_t2, "foo"); - } - t1.enumerate_string_column(col_t1); - CHECK(t1 == t2); - Obj obj1 = t1.get_object(keys_t1[50]); - Obj obj2 = t2.get_object(keys_t2[50]); - obj1.set(col_t1, "bar"); - CHECK(t1 != t2); - obj1.set(col_t1, "foo"); - CHECK(t1 == t2); - obj2.set(col_t2, "bar"); - CHECK(t1 != t2); - obj2.set(col_t2, "foo"); - CHECK(t1 == t2); -} - - TEST(Table_SlabAlloc) { SlabAlloc alloc; @@ -1756,56 +1588,6 @@ TEST(Table_SlabAlloc) #endif } -TEST(Table_NullInEnum) -{ - Group group; - TableRef table = group.add_table("test"); - auto col = table->add_column(type_String, "second", true); - - for (size_t c = 0; c < 100; c++) { - table->create_object().set(col, "hello"); - } - - size_t r; - - r = table->where().equal(col, "hello").count(); - CHECK_EQUAL(100, r); - - Obj obj50 = table->get_object(ObjKey(50)); - obj50.set(col, realm::null()); - r = table->where().equal(col, "hello").count(); - CHECK_EQUAL(99, r); - - table->enumerate_string_column(col); - - obj50.set(col, realm::null()); - r = table->where().equal(col, "hello").count(); - CHECK_EQUAL(99, r); - - obj50.set(col, "hello"); - r = table->where().equal(col, "hello").count(); - CHECK_EQUAL(100, r); - - obj50.set(col, realm::null()); - r = table->where().equal(col, "hello").count(); - CHECK_EQUAL(99, r); - - r = table->where().equal(col, realm::null()).count(); - CHECK_EQUAL(1, r); - - table->get_object(ObjKey(55)).set(col, realm::null()); - r = table->where().equal(col, realm::null()).count(); - CHECK_EQUAL(2, r); - - r = table->where().equal(col, "hello").count(); - CHECK_EQUAL(98, r); - - table->remove_object(ObjKey(55)); - r = table->where().equal(col, realm::null()).count(); - CHECK_EQUAL(1, r); -} - - TEST(Table_DateAndBinary) { Table t; @@ -2122,22 +1904,6 @@ TEST(Table_EmptyMinmax) CHECK(is_null); } -TEST(Table_EnumStringInsertEmptyRow) -{ - Table table; - auto col_str = table.add_column(type_String, "strings"); - for (int i = 0; i < 128; ++i) - table.create_object().set(col_str, "foo"); - - CHECK_EQUAL(0, table.get_num_unique_values(col_str)); - table.enumerate_string_column(col_str); - // Make sure we now have an enumerated strings column - CHECK_EQUAL(1, table.get_num_unique_values(col_str)); - Obj obj = table.create_object(); - CHECK_EQUAL("", obj.get(col_str)); - CHECK_EQUAL(2, table.get_num_unique_values(col_str)); -} - TEST(Table_AddColumnWithThreeLevelBptree) { Table table; @@ -2256,24 +2022,14 @@ TEST(Table_NullableChecks) TEST(Table_Nulls) { - // 'round' lets us run this entire test both with and without index and with/without optimize/enum - for (size_t round = 0; round < 5; round++) { + // 'round' lets us run this entire test both with and without index + for (size_t round = 0; round < 2; round++) { Table t; TableView tv; auto col_str = t.add_column(type_String, "str", true /*nullable*/); if (round == 1) t.add_search_index(col_str); - else if (round == 2) - t.enumerate_string_column(col_str); - else if (round == 3) { - t.add_search_index(col_str); - t.enumerate_string_column(col_str); - } - else if (round == 4) { - t.enumerate_string_column(col_str); - t.add_search_index(col_str); - } std::vector keys; t.create_objects(3, keys); diff --git a/test/test_table_view.cpp b/test/test_table_view.cpp index a7f9e1ac8da..72ce797cd5f 100644 --- a/test/test_table_view.cpp +++ b/test/test_table_view.cpp @@ -891,32 +891,6 @@ TEST(TableView_QueryCopyStringOr) CHECK_EQUAL(after_copy_count, 4); } -TEST(TableView_SortEnum) -{ - Table table; - auto col = table.add_column(type_String, "str"); - - table.create_object().set_all("foo"); - table.create_object().set_all("foo"); - table.create_object().set_all("foo"); - - table.enumerate_string_column(col); - - table.create_object().set_all("bbb"); - table.create_object().set_all("aaa"); - table.create_object().set_all("baz"); - - TableView tv = table.where().find_all(); - tv.sort(col); - - CHECK_EQUAL(tv[0].get(col), "aaa"); - CHECK_EQUAL(tv[1].get(col), "baz"); - CHECK_EQUAL(tv[2].get(col), "bbb"); - CHECK_EQUAL(tv[3].get(col), "foo"); - CHECK_EQUAL(tv[4].get(col), "foo"); - CHECK_EQUAL(tv[5].get(col), "foo"); -} - TEST(TableView_Backlinks) { Group group; @@ -1319,20 +1293,6 @@ TEST_TYPES(TableView_Distinct, DistinctDirect, DistinctOverLink) CHECK_EQUAL(h.get_key(tv, 3), k0); CHECK_EQUAL(h.get_key(tv, 4), k1); - - // Same as previous test, but with string column being Enum - t.enumerate_string_column(col_str); - tv = h.find_all(); - tv.distinct(h.get_distinct({col_str, col_int})); - tv.sort(h.get_sort({col_str}, {false})); - CHECK_EQUAL(tv.size(), 5); - CHECK_EQUAL(h.get_key(tv, 0), k4); - CHECK_EQUAL(h.get_key(tv, 1), k5); - CHECK_EQUAL(h.get_key(tv, 2), k6); - CHECK_EQUAL(h.get_key(tv, 3), k0); - CHECK_EQUAL(h.get_key(tv, 4), k1); - - // Now test sync_if_needed() tv = h.find_all(); // "", null, "", null, "foo", "foo", "bar" diff --git a/test/test_transactions.cpp b/test/test_transactions.cpp index fbbdd314379..f45a576e9cd 100644 --- a/test/test_transactions.cpp +++ b/test/test_transactions.cpp @@ -544,41 +544,4 @@ TEST(Transactions_Continuous_SerialWrites) } } - -// Check that enumeration is gone after -// rolling back the insertion of a string enum column -TEST(LangBindHelper_RollbackStringEnumInsert) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist_w(make_in_realm_history()); - auto sg_w = DB::create(*hist_w, path); - auto g = sg_w->start_write(); - auto t = g->add_table("t1"); - auto col = t->add_column(type_String, "t1_col0_string"); - - auto populate_with_string_enum = [&]() { - t->create_object().set_all("simple_string"); - t->create_object().set_all("duplicate"); - t->create_object().set_all("duplicate"); - t->enumerate_string_column(col); // upgrade to internal string enum column type - CHECK(t->is_enumerated(col)); - CHECK_EQUAL(t->get_num_unique_values(col), 2); - }; - - g->commit_and_continue_as_read(); - g->promote_to_write(); - - populate_with_string_enum(); - - g->rollback_and_continue_as_read(); - g->promote_to_write(); - CHECK(!t->is_enumerated(col)); - populate_with_string_enum(); - - t->begin()->set(col, "duplicate"); - - g->commit_and_continue_as_read(); - CHECK(t->is_enumerated(col)); -} - #endif // TEST_TRANSACTIONS From 932c09d3170e286bac68cf373e143c87ec3072a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Edelbo?= Date: Tue, 2 Jul 2024 14:50:29 +0200 Subject: [PATCH 2/4] Remove realm-enumerate tool --- src/realm/exec/CMakeLists.txt | 11 --- src/realm/exec/realm_enumerate.cpp | 139 ----------------------------- 2 files changed, 150 deletions(-) delete mode 100644 src/realm/exec/realm_enumerate.cpp diff --git a/src/realm/exec/CMakeLists.txt b/src/realm/exec/CMakeLists.txt index 969b45a9e10..28a8a3fe19d 100644 --- a/src/realm/exec/CMakeLists.txt +++ b/src/realm/exec/CMakeLists.txt @@ -46,17 +46,6 @@ endif() target_link_libraries(ClickQuery Storage) -add_executable(RealmEnumerate realm_enumerate.cpp) -set_target_properties(RealmEnumerate PROPERTIES - OUTPUT_NAME "realm-enumerate" - DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} -) -target_link_libraries(RealmEnumerate ObjectStore) -# FIXME can be fixed for others, but requires link and install fixes for libuv target -if (NOT APPLE) - set_target_properties(RealmEnumerate PROPERTIES EXCLUDE_FROM_ALL TRUE) -endif() - add_executable(RealmDecrypt realm_decrypt.cpp) set_target_properties(RealmDecrypt PROPERTIES OUTPUT_NAME "realm-decrypt" diff --git a/src/realm/exec/realm_enumerate.cpp b/src/realm/exec/realm_enumerate.cpp deleted file mode 100644 index 44f534c8454..00000000000 --- a/src/realm/exec/realm_enumerate.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Useage: realm-enumerate [--key crypt_key] [--threshold 0.xx] - * Changes string columns which pass the threshold of unique values to enumerated columns - * and compacts the Realm in place. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -static void enumerate_strings(realm::SharedRealm realm, double threshold) -{ - auto& group = realm->read_group(); - auto table_keys = group.get_table_keys(); - for (auto table_key : table_keys) { - realm::TableRef t = group.get_table(table_key); - size_t table_size = t->size(); - realm::util::format(std::cout, "Begin table '%1' of size %2:\n", t->get_name(), table_size); - if (table_size == 0) - continue; - bool found_str_col = false; - auto do_convert = [&realm, &t](realm::ColKey col) { - auto start = std::chrono::steady_clock::now(); - std::cout << "[converting]" << std::flush; - realm->begin_transaction(); - t->enumerate_string_column(col); - realm->commit_transaction(); - std::chrono::duration diff = std::chrono::steady_clock::now() - start; - std::cout << " (" << diff.count() << " seconds)" << std::endl; - }; - t->for_each_public_column([&](realm::ColKey col_key) { - if (col_key.get_type() == realm::col_type_String && !col_key.is_collection()) { - found_str_col = true; - realm::util::format(std::cout, "\tcolumn '%1' ", t->get_column_name(col_key)); - std::cout << std::flush; - if (t->is_enumerated(col_key)) { - std::cout << "[already enumerated]" << std::endl; - } - else if (t->get_primary_key_column() == col_key) { - std::cout << "[pk - skipping]" << std::endl; - } - else if (threshold >= 100) { - do_convert(col_key); - } - else if (threshold < 100 && threshold > 0) { - std::unique_ptr distinct = - std::make_unique(); - distinct->append_distinct(realm::DistinctDescriptor({{col_key}})); - size_t uniques = t->where().count(*distinct.get()); - double utilization = uniques / double(table_size); - realm::util::format(std::cout, "contains %1 unique values (%2%%) ", uniques, utilization * 100.0); - std::cout << std::flush; - if (utilization <= threshold / 100) { - do_convert(col_key); - } - else { - std::cout << "[skipping due to threshold]" << std::endl; - } - } - else { - std::cout << "[skipping due to threshold]" << std::endl; - } - } - return realm::IteratorControl::AdvanceToNext; - }); - if (!found_str_col) { - std::cout << "\tNo string columns found." << std::endl; - } - } -} - -int main(int argc, const char* argv[]) -{ - if (argc > 1) { - try { - const char* key_ptr = nullptr; - char key[64]; - double threshold = 0; // by default don't convert, just compact - for (int curr_arg = 1; curr_arg < argc; curr_arg++) { - if (strcmp(argv[curr_arg], "--key") == 0) { - std::ifstream key_file(argv[curr_arg + 1]); - key_file.read(key, sizeof(key)); - key_ptr = key; - curr_arg++; - } - else if (strcmp(argv[curr_arg], "--threshold") == 0) { - threshold = strtod(argv[curr_arg + 1], nullptr); - curr_arg++; - } - else { - realm::util::format(std::cout, "File name '%1' for threshold %2%%\n", argv[curr_arg], threshold); - auto start = std::chrono::steady_clock::now(); - realm::Realm::Config config; - config.path = argv[curr_arg]; - if (key_ptr) { - config.encryption_key.resize(64); - memcpy(&config.encryption_key[0], &key_ptr[0], 64); - } - realm::SharedRealm realm; - try { - realm = realm::Realm::get_shared_realm(config); - } - catch (const realm::FileAccessError& e) { - std::cout << "trying to open as a sync Realm\n" << e.what() << "\n" << std::endl; - config.force_sync_history = true; - realm = realm::Realm::get_shared_realm(config); - } - enumerate_strings(realm, threshold); - realm->compact(); - std::chrono::duration diff = std::chrono::steady_clock::now() - start; - std::cout << "Done in " << diff.count() << " seconds." << std::endl; - std::cout << std::endl; - return 0; - } - } - } - catch (const std::exception& e) { - std::cout << e.what() << std::endl; - } - } - else { - std::cout << "Usage: realm-enumerate [--key crypt_key] [--threshold 0.xx] " << std::endl; - std::cout << "The optional crypt_key arg is a filename which contains the 64 byte key." << std::endl; - std::cout - << "The optional threshold is a number between [0, 100] indicating the percentage of unique strings " - "below which columns will be converted. At a value of 100, all columns will be converted. " - "For value of 50 only columns which have 50% or fewer unique values will be converted." - "If not set, the threshold default is 0 which just compacts the file without converting anything." - << std::endl; - } - - return 0; -} From 04a17b6d47d0383c68fee50bf4d17e67b068c04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Edelbo?= Date: Mon, 8 Jul 2024 12:26:29 +0200 Subject: [PATCH 3/4] Remove unused stuff from Spec --- src/realm/spec.cpp | 58 ++++------------------------------------------ src/realm/spec.hpp | 6 ++--- 2 files changed, 6 insertions(+), 58 deletions(-) diff --git a/src/realm/spec.cpp b/src/realm/spec.cpp index 19fca5956b4..1a6b4dfefaa 100644 --- a/src/realm/spec.cpp +++ b/src/realm/spec.cpp @@ -51,14 +51,6 @@ void Spec::init(MemRef mem) noexcept m_top.add(0); } - // Enumkeys array is only there when there are StringEnum columns - if (auto ref = m_top.get_as_ref(s_enum_keys_ndx)) { - m_enumkeys.init_from_ref(ref); - } - else { - m_enumkeys.detach(); - } - if (m_top.get_as_ref(s_col_keys_ndx) == 0) { // This is an upgrade - create column key array MemRef mem_ref = Array::create_empty_array(Array::type_Normal, false, m_top.get_alloc()); // Throws @@ -96,14 +88,6 @@ void Spec::update_from_parent() noexcept m_types.update_from_parent(); m_names.update_from_parent(); m_attr.update_from_parent(); - - if (m_top.get_as_ref(s_enum_keys_ndx) != 0) { - m_enumkeys.update_from_parent(); - } - else { - m_enumkeys.detach(); - } - m_keys.update_from_parent(); update_internals(); @@ -115,36 +99,25 @@ MemRef Spec::create_empty_spec(Allocator& alloc) // The 'spec_set' contains the specification (types and names) of // all columns and sub-tables Array spec_set(alloc); - _impl::DeepArrayDestroyGuard dg(&spec_set); spec_set.create(Array::type_HasRefs); // Throws - _impl::DeepArrayRefDestroyGuard dg_2(alloc); { // One type for each column bool context_flag = false; MemRef mem = Array::create_empty_array(Array::type_Normal, context_flag, alloc); // Throws - dg_2.reset(mem.get_ref()); - int_fast64_t v(from_ref(mem.get_ref())); - spec_set.add(v); // Throws - dg_2.release(); + spec_set.add(from_ref(mem.get_ref())); // Throws } { size_t size = 0; // One name for each column MemRef mem = ArrayStringShort::create_array(size, alloc); // Throws - dg_2.reset(mem.get_ref()); - int_fast64_t v = from_ref(mem.get_ref()); - spec_set.add(v); // Throws - dg_2.release(); + spec_set.add(from_ref(mem.get_ref())); // Throws } { // One attrib set for each column bool context_flag = false; MemRef mem = Array::create_empty_array(Array::type_Normal, context_flag, alloc); // Throws - dg_2.reset(mem.get_ref()); - int_fast64_t v = from_ref(mem.get_ref()); - spec_set.add(v); // Throws - dg_2.release(); + spec_set.add(from_ref(mem.get_ref())); // Throws } spec_set.add(0); // Nested collections array spec_set.add(0); // Enumkeys array @@ -152,13 +125,9 @@ MemRef Spec::create_empty_spec(Allocator& alloc) // One key for each column bool context_flag = false; MemRef mem = Array::create_empty_array(Array::type_Normal, context_flag, alloc); // Throws - dg_2.reset(mem.get_ref()); - int_fast64_t v = from_ref(mem.get_ref()); - spec_set.add(v); // Throws - dg_2.release(); + spec_set.add(from_ref(mem.get_ref())); // Throws } - dg.release(); return spec_set.get_mem(); } @@ -204,10 +173,6 @@ void Spec::insert_column(size_t column_ndx, ColKey col_key, ColumnType type, Str m_attr.insert(column_ndx, attr); // Throws m_keys.insert(column_ndx, col_key.value); - if (m_enumkeys.is_attached() && type != col_type_BackLink) { - m_enumkeys.insert(column_ndx, 0); - } - update_internals(); } @@ -216,21 +181,6 @@ void Spec::erase_column(size_t column_ndx) REALM_ASSERT(column_ndx < m_types.size()); if (ColumnType(int(m_types.get(column_ndx))) != col_type_BackLink) { - // Remove this column from the enum keys lookup and clean it up if it's now empty - if (m_enumkeys.is_attached()) { - m_enumkeys.erase(column_ndx); // Throws - bool all_empty = true; - for (size_t i = 0; i < m_enumkeys.size(); i++) { - if (m_enumkeys.get(i) != 0) { - all_empty = false; - break; - } - } - if (all_empty) { - m_enumkeys.destroy_deep(); - m_top.set(4, 0); - } - } m_num_public_columns--; m_names.erase(column_ndx); // Throws } diff --git a/src/realm/spec.hpp b/src/realm/spec.hpp index f361c61e9ef..3a80892eaeb 100644 --- a/src/realm/spec.hpp +++ b/src/realm/spec.hpp @@ -91,7 +91,7 @@ class Spec { static constexpr size_t s_names_ndx = 1; static constexpr size_t s_attributes_ndx = 2; static constexpr size_t s_vacant_1 = 3; - static constexpr size_t s_enum_keys_ndx = 4; + // static constexpr size_t s_enum_keys_ndx = 4; static constexpr size_t s_col_keys_ndx = 5; static constexpr size_t s_spec_max_size = 6; @@ -100,7 +100,7 @@ class Spec { ArrayStringShort m_names; // 2nd slot in m_top Array m_attr; // 3rd slot in m_top // 4th slot in m_top not cached - Array m_enumkeys; // 5th slot in m_top + // 5th slot in m_top Array m_keys; // 6th slot in m_top size_t m_num_public_columns = 0; @@ -150,13 +150,11 @@ inline Spec::Spec(Allocator& alloc) noexcept , m_types(alloc) , m_names(alloc) , m_attr(alloc) - , m_enumkeys(alloc) , m_keys(alloc) { m_types.set_parent(&m_top, s_types_ndx); m_names.set_parent(&m_top, s_names_ndx); m_attr.set_parent(&m_top, s_attributes_ndx); - m_enumkeys.set_parent(&m_top, s_enum_keys_ndx); m_keys.set_parent(&m_top, s_col_keys_ndx); } From 7f1271f8edc1787992631b5160d467c162b2db79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Edelbo?= Date: Tue, 9 Jul 2024 13:16:58 +0200 Subject: [PATCH 4/4] Updated comments --- src/realm/spec.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/realm/spec.hpp b/src/realm/spec.hpp index 3a80892eaeb..c539dee7b93 100644 --- a/src/realm/spec.hpp +++ b/src/realm/spec.hpp @@ -99,8 +99,8 @@ class Spec { Array m_types; // 1st slot in m_top ArrayStringShort m_names; // 2nd slot in m_top Array m_attr; // 3rd slot in m_top - // 4th slot in m_top not cached - // 5th slot in m_top + // 4th slot in m_top, old subspecs. Not used since v6.0.0 + // 5th slot in m_top, old enum keys which was never released Array m_keys; // 6th slot in m_top size_t m_num_public_columns = 0;