diff --git a/CHANGELOG.md b/CHANGELOG.md index 35793b30..b1129faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ X.Y.Z Release notes (YYYY-MM-DD) ### Fixed * Managed objects would exhibit undefined behaviour when returned from the subscript operator in `std::vector` & `std::map`. +* Type safe queries would not work correctly when link properties were used. ### Enhancements * Add `realm::holds_alternative` which acts as a substitute to `std::holds_alternative` when using `managed`. @@ -18,7 +19,7 @@ X.Y.Z Release notes (YYYY-MM-DD) * Fileformat: Generates files with format v23. Reads and automatically upgrade from fileformat v5. ### Internals -* None +* Upgraded to Core v14.1.0 ---------------------------------------------- @@ -313,4 +314,4 @@ The following functions now return `std::future` instead of `std::promise` ### Internals * Upgraded to Core v13.9.2 ----------------------------------------------- \ No newline at end of file +---------------------------------------------- diff --git a/Package.swift b/Package.swift index 83182dee..9d177325 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,7 @@ import PackageDescription let sdkVersion = Version("1.0.0") -let coreVersion = Version("13.26.0") +let coreVersion = Version("14.1.0") var cxxSettings: [CXXSetting] = [ .define("REALM_ENABLE_SYNC", to: "1"), @@ -61,7 +61,7 @@ let package = Package( targets: ["realm-cpp-sdk"]), ], dependencies: [ - .package(url: "https://github.com/realm/realm-core.git", revision: "334d534a49b39d70f1b2ae5d982272e30f74dd82") + .package(url: "https://github.com/realm/realm-core.git", revision: "08c61e87add15b0d7fcd52c818c43fb4804e1216") ], targets: [ cppSdkTarget, @@ -97,6 +97,25 @@ let package = Package( sources: [ "main.hpp", "main.cpp", + "db/binary_tests.cpp", + "db/date_tests.cpp", + "db/decimal_tests.cpp", + "db/embedded_object_tests.cpp", + "db/frozen_tests.cpp", + "db/list_tests.cpp", + "db/map_tests.cpp", + "db/mixed_tests.cpp", + "db/numeric_tests.cpp", + "db/object_id_tests.cpp", + "db/object_tests.cpp", + "db/optional_tests.cpp", + "db/performance_tests.cpp", + "db/query_tests.cpp", + "db/realm_tests.cpp", + "db/results_tests.cpp", + "db/run_loop_tests.cpp", + "db/set_tests.cpp", + "db/string_tests.cpp" ], resources: [ .copy("setup_baas.rb"), diff --git a/ports/portfile.cmake b/ports/portfile.cmake index 49481c7c..8f854ad6 100644 --- a/ports/portfile.cmake +++ b/ports/portfile.cmake @@ -8,7 +8,7 @@ vcpkg_execute_required_process( LOGNAME submodules ) -set(CPPREALM_CMAKE_OPTIONS -DREALM_CPP_NO_TESTS=ON) +set(CPPREALM_CMAKE_OPTIONS -DREALM_CPP_NO_TESTS=ON -DREALM_CORE_SUBMODULE_BUILD=OFF) if (ANDROID OR WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux") list(APPEND CPPREALM_CMAKE_OPTIONS -DREALM_USE_SYSTEM_OPENSSL=ON) diff --git a/realm-core b/realm-core index 334d534a..2bfd5e9b 160000 --- a/realm-core +++ b/realm-core @@ -1 +1 @@ -Subproject commit 334d534a49b39d70f1b2ae5d982272e30f74dd82 +Subproject commit 2bfd5e9ba74ed2620657bf968d2931f6ceab6785 diff --git a/src/cpprealm/flex_sync.hpp b/src/cpprealm/flex_sync.hpp index 089936a0..2d4650c2 100644 --- a/src/cpprealm/flex_sync.hpp +++ b/src/cpprealm/flex_sync.hpp @@ -90,14 +90,15 @@ namespace realm { auto schema = m_realm.get().schema().find(managed::schema.name); auto group = m_realm.get().read_group(); auto table_ref = group.get_table(schema.table_key()); - auto builder = internal::bridge::query(table_ref); + auto root_query = internal::bridge::query(table_ref); if (query_fn) { - auto q = realm::query>(builder, std::move(schema), m_realm); - auto full_query = (*query_fn)(q).q; + rbool query = rbool(std::move(root_query)); + auto query_object = managed::prepare_for_query(m_realm, &query); + auto full_query = (*query_fn)(query_object).q; insert_or_assign(name, full_query); } else { - insert_or_assign(name, builder); + insert_or_assign(name, root_query); } } diff --git a/src/cpprealm/internal/bridge/mixed.cpp b/src/cpprealm/internal/bridge/mixed.cpp index 5ba49792..99093656 100644 --- a/src/cpprealm/internal/bridge/mixed.cpp +++ b/src/cpprealm/internal/bridge/mixed.cpp @@ -24,10 +24,12 @@ namespace realm::internal::bridge { } mixed::mixed(const mixed& other) { - if (other.type() == data_type::String) { - m_owned_string = other.m_owned_string; - } else if (other.type() == data_type::Binary) { - m_owned_data = other.m_owned_data; + if (!other.is_null()) { + if (other.type() == data_type::String) { + m_owned_string = other.m_owned_string; + } else if (other.type() == data_type::Binary) { + m_owned_data = other.m_owned_data; + } } #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES @@ -39,10 +41,12 @@ namespace realm::internal::bridge { mixed& mixed::operator=(const mixed& other) { if (this != &other) { - if (other.type() == data_type::String) { - m_owned_string = other.m_owned_string; - } else if (other.type() == data_type::Binary) { - m_owned_data = other.m_owned_data; + if (!other.is_null()) { + if (other.type() == data_type::String) { + m_owned_string = other.m_owned_string; + } else if (other.type() == data_type::Binary) { + m_owned_data = other.m_owned_data; + } } #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES *reinterpret_cast(&m_mixed) = *reinterpret_cast(&other.m_mixed); diff --git a/src/cpprealm/internal/bridge/query.cpp b/src/cpprealm/internal/bridge/query.cpp index 340b2397..8beeadc3 100644 --- a/src/cpprealm/internal/bridge/query.cpp +++ b/src/cpprealm/internal/bridge/query.cpp @@ -10,6 +10,7 @@ #include #include +#include #define __generate_query_operator(op, type) \ query &query::op(col_key column_key, type value) { \ @@ -29,6 +30,378 @@ return *this; \ } namespace realm::internal::bridge { + + + subexpr::subexpr(std::unique_ptr other) { + m_subexpr = std::move(other); + } + + // INT + query subexpr::equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == rhs; + } + + query subexpr::not_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != rhs; + } + + query subexpr::greater(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) > rhs; + } + + query subexpr::less(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) < rhs; + } + + query subexpr::greater_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= rhs; + } + + query subexpr::less_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) <= rhs; + } + + // BOOL + query subexpr::equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == rhs; + } + + query subexpr::not_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != rhs; + } + + // DOUBLE + query subexpr::equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == rhs; + } + + query subexpr::not_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != rhs; + } + + query subexpr::greater(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) > rhs; + } + + query subexpr::less(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) < rhs; + } + + query subexpr::greater_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= rhs; + } + + query subexpr::less_equal(const std::optional& rhs) const { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) <= rhs; + } + + // BINARY + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + // TIMESTAMP + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + query subexpr::greater(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) > *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) > ::realm::null(); + } + } + + query subexpr::less(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) < *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) < ::realm::null(); + } + } + + query subexpr::greater_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= ::realm::null(); + } + } + + query subexpr::less_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) <= *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) <= ::realm::null(); + } + } + + // UUID + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + // OBJECT_ID + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + // DECIMAL128 + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + query subexpr::greater(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) > *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) > ::realm::null(); + } + } + + query subexpr::less(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) < *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) < ::realm::null(); + } + } + + query subexpr::greater_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= ::realm::null(); + } + } + + query subexpr::less_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) <= *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) <= ::realm::null(); + } + } + + // STRING + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) >= ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + query subexpr::contains(const std::optional& rhs, bool case_sensitive) const { + return std::dynamic_pointer_cast<::realm::Columns>(m_subexpr)->contains(rhs, case_sensitive); + } + + // MIXED + query subexpr::mixed_equal(const internal::bridge::mixed& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == rhs.operator Mixed(); + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == ::realm::null(); + } + } + + query subexpr::mixed_not_equal(const internal::bridge::mixed& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != rhs.operator Mixed(); + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + // LINKS + query subexpr::equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) == *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + query subexpr::not_equal(const std::optional& rhs) const { + if (rhs) { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != *rhs; + } else { + return *std::dynamic_pointer_cast<::realm::Columns>(m_subexpr) != ::realm::null(); + } + } + + link_chain::link_chain() { + m_link_chain = std::make_shared(); + } + + link_chain::link_chain(const link_chain& other) { + m_link_chain = other.m_link_chain; + } + + link_chain& link_chain::operator=(const link_chain& other) { + m_link_chain = other.m_link_chain; + return *this; + } + + link_chain::link_chain(link_chain&& other) { + m_link_chain = std::move(other.m_link_chain); + } + + link_chain& link_chain::operator=(link_chain&& other) { + m_link_chain = std::move(other.m_link_chain); + return *this; + } + + link_chain::link_chain(const LinkChain& other) { + m_link_chain = std::make_shared(other); + } + + link_chain& link_chain::link(col_key ck) { + m_link_chain->link(ck); + return *this; + } + + link_chain& link_chain::link(std::string col_name) { + m_link_chain->link(col_name); + return *this; + } + + link_chain& link_chain::backlink(const table& origin, col_key origin_col_key) { + reinterpret_cast(&m_link_chain)->backlink(origin.operator ConstTableRef().operator*(), origin_col_key); + return *this; + } + + template<> + subexpr link_chain::column(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column>(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column>(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column<::realm::decimal128>(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column<::realm::object_id>(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column<::realm::uuid>(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + template<> + subexpr link_chain::column(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + subexpr link_chain::column_mixed(col_key col_name) { + return m_link_chain->column(col_name).clone(); + } + + subexpr link_chain::subquery(query subquery) { + return reinterpret_cast(&m_link_chain)->subquery(subquery); + } + + table link_chain::get_table() { + return reinterpret_cast(&m_link_chain)->get_current_table(); + } + query::query() { #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES new (&m_query) Query(); @@ -171,27 +544,45 @@ namespace realm::internal::bridge { __generate_query_operator(equal, bool) __generate_query_operator(not_equal, bool) + query& links_to(col_key column_key, bool value); + query& query::links_to(col_key column_key, const internal::bridge::obj& o) { +#ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES + *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->links_to(column_key, o.get_key()); +#else + m_query = std::make_shared(m_query->links_to(column_key, o.get_key())); +#endif + return *this; + } + + query& query::not_links_to(col_key column_key, const internal::bridge::obj& o) { +#ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES + *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->not_links_to(column_key, {o.get_key()}); +#else + m_query = std::make_shared(m_query->not_links_to(column_key, {o.get_key()})); +#endif + return *this; + } query& query::equal(col_key column_key, std::nullopt_t) { #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES - *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->equal(column_key, realm::null{}); + *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->equal(column_key, ::realm::null{}); #else - m_query = std::make_shared(m_query->equal(column_key, realm::null{})); + m_query = std::make_shared(m_query->equal(column_key, ::realm::null{})); #endif return *this; } query& query::not_equal(col_key column_key, std::nullopt_t) { #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES - *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->not_equal(column_key, realm::null{}); + *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->not_equal(column_key, ::realm::null{}); #else - m_query = std::make_shared(m_query->not_equal(column_key, realm::null{})); + m_query = std::make_shared(m_query->not_equal(column_key, ::realm::null{})); #endif return *this; } query& query::negate() { #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES - *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->Not(); + *reinterpret_cast(&m_query) = reinterpret_cast(&m_query)->operator!(); #else m_query = std::make_shared(m_query->operator!()); #endif diff --git a/src/cpprealm/internal/bridge/query.hpp b/src/cpprealm/internal/bridge/query.hpp index b6fe7cce..f19141e9 100644 --- a/src/cpprealm/internal/bridge/query.hpp +++ b/src/cpprealm/internal/bridge/query.hpp @@ -20,6 +20,7 @@ #define CPPREALM_BRIDGE_QUERY_HPP #include +#include #include #include @@ -29,7 +30,9 @@ namespace realm { struct object_id; struct decimal128; struct uuid; + class LinkChain; class Query; + class Subexpr; } namespace realm::internal::bridge { struct table; @@ -41,6 +44,89 @@ namespace realm::internal::bridge { struct uuid; struct mixed; + struct subexpr { + subexpr(subexpr&& other) = default; + subexpr& operator=(subexpr&& other) = default; + ~subexpr() = default; + subexpr(std::unique_ptr other); + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + query greater(const std::optional& rhs) const; + query less(const std::optional& rhs) const; + query greater_equal(const std::optional& rhs) const; + query less_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + query greater(const std::optional& rhs) const; + query less(const std::optional& rhs) const; + query greater_equal(const std::optional& rhs) const; + query less_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + query greater(const std::optional& rhs) const; + query less(const std::optional& rhs) const; + query greater_equal(const std::optional& rhs) const; + query less_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + query contains(const std::optional& rhs, bool case_sensitive = true) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + + query equal(const std::optional& rhs) const; + query not_equal(const std::optional& rhs) const; + query greater(const std::optional& rhs) const; + query less(const std::optional& rhs) const; + query greater_equal(const std::optional& rhs) const; + query less_equal(const std::optional& rhs) const; + + query mixed_equal(const internal::bridge::mixed& rhs) const; + query mixed_not_equal(const internal::bridge::mixed& rhs) const; + + query equal(const std::optional&) const; + query not_equal(const std::optional&) const; + + private: + std::shared_ptr m_subexpr; + }; + + struct link_chain { + link_chain(); + link_chain(const link_chain& other) ; + link_chain& operator=(const link_chain& other) ; + link_chain(link_chain&& other); + link_chain& operator=(link_chain&& other); + ~link_chain() = default; + link_chain(const LinkChain& other); + + link_chain& link(col_key); + link_chain& link(std::string col_name); + link_chain& backlink(const table& origin, col_key origin_col_key); + + template + subexpr column(col_key); + subexpr column_mixed(col_key); + + subexpr subquery(query subquery); + table get_table(); + + private: + std::shared_ptr m_link_chain; + }; struct query { query(); @@ -141,7 +227,10 @@ namespace realm::internal::bridge { // Conditions: bool query& equal(col_key column_key, bool value); query& not_equal(col_key column_key, bool value); - using underlying = Query; + + // Conditions: links + query& links_to(col_key column_key, const internal::bridge::obj& o); + query& not_links_to(col_key column_key, const internal::bridge::obj& o); std::string description() const; private: diff --git a/src/cpprealm/internal/bridge/realm.cpp b/src/cpprealm/internal/bridge/realm.cpp index b0eb2b45..dd9b16db 100644 --- a/src/cpprealm/internal/bridge/realm.cpp +++ b/src/cpprealm/internal/bridge/realm.cpp @@ -45,7 +45,9 @@ namespace realm::internal::bridge { class null_logger : public ::realm::logger { public: - null_logger() = default; + null_logger() { + set_level_threshold(logger::level::off); + }; void do_log(logger::level, const std::string&) override {} }; @@ -245,8 +247,9 @@ namespace realm::internal::bridge { realm::realm(const config &v) { static bool initialized; if (!initialized) { - set_default_level_threshold(logger::level::off); - set_default_logger(std::make_shared()); + auto logger = std::make_shared(); + logger->set_level_threshold(logger::level::off); + set_default_logger(logger); realm_analytics::send(); initialized = true; } diff --git a/src/cpprealm/internal/bridge/table.cpp b/src/cpprealm/internal/bridge/table.cpp index 158aa657..7a205c08 100644 --- a/src/cpprealm/internal/bridge/table.cpp +++ b/src/cpprealm/internal/bridge/table.cpp @@ -4,12 +4,12 @@ #include #include -#include #include #include #include namespace realm::internal::bridge { + table::table() { #ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES new (&m_table) TableRef(); @@ -134,6 +134,10 @@ namespace realm::internal::bridge { return static_cast(*this)->get_link_target(col_key); } + link_chain table::get_link(const col_key col_key) const { + return static_cast(*this)->link(col_key); + } + obj table::create_object_with_primary_key(const bridge::mixed& key) const { return static_cast(*this)->create_object_with_primary_key(key.operator ::realm::Mixed()); } diff --git a/src/cpprealm/internal/bridge/table.hpp b/src/cpprealm/internal/bridge/table.hpp index 47590f50..73f76165 100644 --- a/src/cpprealm/internal/bridge/table.hpp +++ b/src/cpprealm/internal/bridge/table.hpp @@ -29,10 +29,12 @@ namespace realm { class Mixed; class TableView; + namespace internal::bridge { - struct obj; - struct mixed; struct col_key; + struct link_chain; + struct mixed; + struct obj; struct query; struct table { @@ -56,10 +58,12 @@ namespace realm { obj create_object(const obj_key &obj_key = {}) const; table get_link_target(const col_key col_key) const; + link_chain get_link(const col_key col_key) const; [[nodiscard]] bool is_embedded() const; struct query query(const std::string &, const std::vector &) const; + struct query where() const; void remove_object(const obj_key &) const; obj get_object(const obj_key&) const; diff --git a/src/cpprealm/link.hpp b/src/cpprealm/link.hpp index 9fd55f10..696f77a1 100644 --- a/src/cpprealm/link.hpp +++ b/src/cpprealm/link.hpp @@ -20,8 +20,10 @@ #define CPPREALM_BRIDGE_LINK_HPP #include -#include #include +#include + +#include namespace realm { template @@ -91,8 +93,9 @@ namespace realm { managed m_managed; }; ref_type operator ->() const { - if (should_detect_usage_for_queries) { - return ref_type(managed::prepare_for_query(*m_realm)); + if (this->m_rbool_query) { + this->m_rbool_query->add_link_chain(m_realm, m_key); + return ref_type(managed::prepare_for_query(*m_realm, this->m_rbool_query)); } return ref_type(managed(m_obj->get_linked_object(m_key), *m_realm)); } @@ -145,30 +148,48 @@ namespace realm { return *this; } - bool operator ==(const std::nullptr_t) const { + rbool operator ==(std::nullptr_t) const { + if (m_rbool_query) { + return m_rbool_query->link_equal(m_key, std::nullopt); + } return !m_obj->get_linked_object(m_key).is_valid(); } - bool operator ==(const managed& rhs) const { + rbool operator ==(const managed& rhs) const { + if (m_rbool_query) { + return m_rbool_query->link_equal(m_key, rhs.m_obj); + } if (*this->m_realm != rhs.m_realm) return false; return m_obj->get_linked_object(m_key).get_key() == rhs.m_obj.get_key(); } - bool operator ==(const managed& rhs) const { + rbool operator ==(const managed& rhs) const { + if (m_rbool_query) { + return m_rbool_query->link_equal(m_key, *rhs.m_obj); + } if (*this->m_realm != *rhs.m_realm) return false; return m_obj->get_linked_object(m_key).get_key() == rhs.m_obj->get_key(); } - bool operator !=(const std::nullptr_t) const { - return !this->operator==(nullptr); + rbool operator !=(std::nullptr_t) const { + if (m_rbool_query) { + return m_rbool_query->link_not_equal(m_key, std::nullopt); + } + return m_obj->get_linked_object(m_key).is_valid(); } - bool operator !=(const managed& rhs) const { - return !this->operator==(rhs); + rbool operator !=(const managed& rhs) const { + if (m_rbool_query) { + return m_rbool_query->link_not_equal(m_key, rhs.m_obj); + } + return m_obj->get_linked_object(m_key).is_valid(); } - bool operator !=(const managed& rhs) const { - return !this->operator==(rhs); + rbool operator !=(const managed& rhs) const { + if (m_rbool_query) { + return m_rbool_query->link_not_equal(m_key, *rhs.m_obj); + } + return m_obj->get_linked_object(m_key).is_valid(); } private: diff --git a/src/cpprealm/logger.cpp b/src/cpprealm/logger.cpp index 1bb4e3c6..e7a78b3f 100644 --- a/src/cpprealm/logger.cpp +++ b/src/cpprealm/logger.cpp @@ -64,10 +64,13 @@ namespace realm { } struct internal_logger : public util::Logger { - internal_logger(std::shared_ptr &&s) { - m_logger = std::move(s); + explicit internal_logger(std::shared_ptr&& logger) { + m_logger = std::move(logger); + this->set_level_threshold(log_level_for_level(m_logger->get_level_threshold())); } - void do_log(util::Logger::Level level, const std::string &msg) override { + + protected: + void do_log(const util::LogCategory&, util::Logger::Level level, const std::string &msg) override { m_logger->do_log(log_level_for_level(level), msg); } @@ -78,7 +81,4 @@ namespace realm { void set_default_logger(std::shared_ptr&& l) { util::Logger::set_default_logger(std::make_shared(std::move(l))); } - void set_default_level_threshold(logger::level l) { - util::Logger::set_default_level_threshold(log_level_for_level(l)); - } } \ No newline at end of file diff --git a/src/cpprealm/logger.hpp b/src/cpprealm/logger.hpp index bd36f294..7f01f93d 100644 --- a/src/cpprealm/logger.hpp +++ b/src/cpprealm/logger.hpp @@ -23,6 +23,7 @@ #include namespace realm { + struct logger { /// Specifies criticality when passed to log(). /// @@ -47,10 +48,18 @@ namespace realm { off = 8 }; virtual void do_log(level, const std::string &) = 0; virtual inline ~logger() noexcept = default; + void set_level_threshold(level l) { + m_level_threshold = l; + } + + level get_level_threshold() const { + return m_level_threshold; + } + protected: + level m_level_threshold; }; void set_default_logger(std::shared_ptr &&); - void set_default_level_threshold(logger::level); } #endif//CPPREALM_LOGGER_HPP diff --git a/src/cpprealm/macros.hpp b/src/cpprealm/macros.hpp index 768cf99f..6fdfd44e 100644 --- a/src/cpprealm/macros.hpp +++ b/src/cpprealm/macros.hpp @@ -260,34 +260,19 @@ FE_19, FE_18, FE_17, FE_16, FE_15, FE_14, FE_13, FE_12, FE_11, FE_10, \ FE_9, FE_8, FE_7, FE_6, FE_5, FE_4, FE_3, FE_2, FE_1, FE_0)(action, cls, __VA_ARGS__) +namespace realm { + template + struct managed; +} + #define DECLARE_PERSISTED(cls, property) managed property; #define DECLARE_PROPERTY(cls, p) realm::property<&cls::p>(#p), #define DECLARE_MANAGED_PROPERTY(cls, p) &realm::managed::p, -#define DECLARE_UNMANAGED_TO_MANAGED_PAIR(cls, p) std::pair {&cls::p, &realm::managed::p}, #define DECLARE_MANAGED_PROPERTY_NAME(cls, p) #p, -#define DECLARE_COND_PROPERTY_VALUE_FOR_NAME(cls, p) if (_name == #p) { auto ptr = &managed::p; return (*this.*ptr).detach(); } #define DECLARE_COND_UNMANAGED_TO_MANAGED(cls, p) if constexpr (std::is_same_v) { return &managed::p; } #include -#define COUNTER_READ_CRUMB( TAG, RANK, ACC ) \ - counter_crumb( TAG(), constant_index< RANK >(), constant_index< ACC >() ) -#define COUNTER_READ( TAG ) COUNTER_READ_CRUMB( TAG, 1, COUNTER_READ_CRUMB( TAG, 2, COUNTER_READ_CRUMB( TAG, 4, COUNTER_READ_CRUMB( TAG, 8, \ - COUNTER_READ_CRUMB( TAG, 16, COUNTER_READ_CRUMB( TAG, 32, COUNTER_READ_CRUMB( TAG, 64, COUNTER_READ_CRUMB( TAG, 128, 0 ) ) ) ) ) ) ) ) - -#define COUNTER_INC( TAG ) \ -constant_index< COUNTER_READ( TAG ) + 1 > \ -constexpr counter_crumb( TAG, constant_index< ( COUNTER_READ( TAG ) + 1 ) & ~ COUNTER_READ( TAG ) >, \ - constant_index< ( COUNTER_READ( TAG ) + 1 ) & COUNTER_READ( TAG ) > ) { return {}; } - -#define COUNTER_LINK_NAMESPACE( NS ) using counter_crumb; - -template< std::size_t n > -struct constant_index : std::integral_constant< std::size_t, n > {}; - -template< typename id, std::size_t rank, std::size_t acc > -constexpr constant_index< acc > counter_crumb( id, constant_index< rank >, constant_index< acc > ) { return {}; } // found by ADL via constant_index - #include #include #include @@ -296,49 +281,42 @@ constexpr constant_index< acc > counter_crumb( id, constant_index< rank >, const #include namespace realm { + class rbool; + struct managed_base { - protected: + protected: managed_base() = default; managed_base(const managed_base& other) { m_obj = other.m_obj; m_realm = other.m_realm; m_key = other.m_key; - // MARK: Queries - should_detect_usage_for_queries = other.should_detect_usage_for_queries; - query = other.query; + m_rbool_query = other.m_rbool_query; } managed_base& operator=(const managed_base& other) { m_obj = other.m_obj; m_realm = other.m_realm; m_key = other.m_key; - // MARK: Queries - should_detect_usage_for_queries = other.should_detect_usage_for_queries; - query = other.query; + m_rbool_query = other.m_rbool_query; return *this; } managed_base(managed_base&& other) { m_obj = std::move(other.m_obj); m_realm = std::move(other.m_realm); m_key = std::move(other.m_key); - // MARK: Queries - should_detect_usage_for_queries = std::move(other.should_detect_usage_for_queries); - query = std::move(other.query); + m_rbool_query = std::move(other.m_rbool_query); } managed_base& operator=(managed_base&& other) { m_obj = std::move(other.m_obj); m_realm = std::move(other.m_realm); m_key = std::move(other.m_key); - // MARK: Queries - should_detect_usage_for_queries = std::move(other.should_detect_usage_for_queries); - query = std::move(other.query); + m_rbool_query = std::move(other.m_rbool_query); return *this; } ~managed_base() { m_obj = nullptr; m_realm = nullptr; + m_rbool_query = nullptr; m_key.~col_key(); - should_detect_usage_for_queries = false; - query = nullptr; } public: static constexpr bool is_object = false; @@ -346,8 +324,7 @@ namespace realm { internal::bridge::realm *m_realm = nullptr; internal::bridge::col_key m_key; // MARK: Queries - bool should_detect_usage_for_queries = false; - internal::bridge::query* query = nullptr; + rbool* m_rbool_query = nullptr; void assign(internal::bridge::obj *obj, internal::bridge::realm* realm, @@ -375,22 +352,17 @@ namespace realm { return *this; } - void prepare_for_query(internal::bridge::query& query_builder) { - should_detect_usage_for_queries = true; - query = &query_builder; - } - void prepare_for_query(internal::bridge::realm* realm, const internal::bridge::table& table, - const std::string_view& col_name) { - this->query = new internal::bridge::query(table); + const std::string_view& col_name, + realm::rbool* query_builder) { this->m_realm = realm; this->m_key = table.get_column_key(col_name); - this->should_detect_usage_for_queries = true; + this->m_rbool_query = query_builder; } }; - template + template struct managed; } @@ -407,24 +379,16 @@ auto zipTuples(const std::tuple& tuple1, const std::tuple& tuple2) #define __cpprealm_build_query(op, name, type) \ rbool managed::operator op(const type& rhs) const noexcept { \ - if (this->should_detect_usage_for_queries) { \ - auto query = internal::bridge::query(this->query->get_table()); \ - query.name(this->m_key, serialize(rhs)); \ - return query; \ + if (this->m_rbool_query) { \ + return this->m_rbool_query->name(m_key, rhs); \ } \ return serialize(detach()) op serialize(rhs); \ } \ #define __cpprealm_build_optional_query(op, name, type) \ rbool managed>::operator op(const std::optional& rhs) const noexcept { \ - if (this->should_detect_usage_for_queries) { \ - auto query = internal::bridge::query(this->query->get_table()); \ - if (auto r = serialize(rhs)) { \ - query.name(this->m_key, *r); \ - } else { \ - query.name(this->m_key, std::nullopt); \ - } \ - return query; \ + if (this->m_rbool_query) { \ + return this->m_rbool_query->name(m_key, rhs); \ } \ return serialize(detach()) op serialize(rhs); \ } \ @@ -466,14 +430,14 @@ rbool managed>::operator op(const std::optional& rhs) managed(const managed& other) { \ m_obj = other.m_obj; \ m_realm = other.m_realm; \ - m_prepare_for_query = other.m_prepare_for_query; \ - if (m_prepare_for_query) { \ + m_rbool_query = other.m_rbool_query; \ + if (m_rbool_query) { \ auto schema = m_realm.schema().find(other.schema.name); \ auto group = m_realm.read_group(); \ auto table_ref = group.get_table(schema.table_key()); \ std::apply([&](auto &&...ptr) { \ std::apply([&](auto &&..._name) { \ - ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name), ...); \ + ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name, m_rbool_query), ...); \ }, managed_pointers_names); \ }, managed_pointers()); \ } else { \ @@ -487,14 +451,14 @@ rbool managed>::operator op(const std::optional& rhs) managed& operator=(const managed& other) { \ m_obj = other.m_obj; \ m_realm = other.m_realm; \ - m_prepare_for_query = other.m_prepare_for_query; \ - if (m_prepare_for_query) { \ + m_rbool_query = other.m_rbool_query; \ + if (m_rbool_query) { \ auto schema = m_realm.schema().find(other.schema.name); \ auto group = m_realm.read_group(); \ auto table_ref = group.get_table(schema.table_key()); \ std::apply([&](auto &&...ptr) { \ std::apply([&](auto &&..._name) { \ - ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name), ...); \ + ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name, m_rbool_query), ...); \ }, managed_pointers_names); \ }, managed_pointers()); \ } else { \ @@ -508,15 +472,15 @@ rbool managed>::operator op(const std::optional& rhs) } \ managed(managed&& other) { \ m_obj = std::move(other.m_obj); \ - m_realm = std::move(other.m_realm); \ - m_prepare_for_query = std::move(other.m_prepare_for_query); \ - if (m_prepare_for_query) { \ + m_realm = std::move(other.m_realm); \ + m_rbool_query = std::move(other.m_rbool_query); \ + if (m_rbool_query) { \ auto schema = m_realm.schema().find(other.schema.name); \ auto group = m_realm.read_group(); \ auto table_ref = group.get_table(schema.table_key()); \ std::apply([&](auto &&...ptr) { \ std::apply([&](auto &&..._name) { \ - ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name), ...); \ + ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name, m_rbool_query), ...); \ }, managed_pointers_names); \ }, managed_pointers()); \ } else { \ @@ -529,15 +493,15 @@ rbool managed>::operator op(const std::optional& rhs) } \ managed& operator=(managed&& other) { \ m_obj = std::move(other.m_obj); \ - m_realm = std::move(other.m_realm); \ - m_prepare_for_query = std::move(other.m_prepare_for_query); \ - if (m_prepare_for_query) { \ + m_realm = std::move(other.m_realm); \ + m_rbool_query = std::move(other.m_rbool_query); \ + if (m_rbool_query) { \ auto schema = m_realm.schema().find(other.schema.name); \ auto group = m_realm.read_group(); \ auto table_ref = group.get_table(schema.table_key()); \ std::apply([&](auto &&...ptr) { \ std::apply([&](auto &&..._name) { \ - ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name), ...); \ + ((*this.*ptr).prepare_for_query(&m_realm, table_ref, _name, m_rbool_query), ...); \ }, managed_pointers_names); \ }, managed_pointers()); \ } else { \ @@ -549,16 +513,16 @@ rbool managed>::operator op(const std::optional& rhs) } \ return *this;\ } \ - static managed prepare_for_query(const internal::bridge::realm& r) { \ + static managed prepare_for_query(const internal::bridge::realm& r, realm::rbool* q) { \ managed m; \ - m.m_prepare_for_query = true; \ - m.m_realm = r; \ + m.m_realm = r; \ + m.m_rbool_query = q; \ auto schema = m.m_realm.schema().find(m.schema.name); \ auto group = m.m_realm.read_group(); \ auto table_ref = group.get_table(schema.table_key()); \ std::apply([&](auto && ...ptr) { \ std::apply([&](auto&& ..._name) { \ - ((m.*ptr).prepare_for_query(&m.m_realm, table_ref, _name), ...); \ + ((m.*ptr).prepare_for_query(&m.m_realm, table_ref, _name, m.m_rbool_query), ...); \ }, managed_pointers_names); \ }, managed_pointers()); \ return m; \ @@ -637,7 +601,7 @@ rbool managed>::operator op(const std::optional& rhs) private: \ internal::bridge::obj m_obj; \ internal::bridge::realm m_realm; \ - bool m_prepare_for_query = false; \ + rbool* m_rbool_query = nullptr; \ friend struct db; \ template friend struct managed; \ template friend struct box; \ diff --git a/src/cpprealm/managed_list.hpp b/src/cpprealm/managed_list.hpp index bc51d914..18497b49 100644 --- a/src/cpprealm/managed_list.hpp +++ b/src/cpprealm/managed_list.hpp @@ -351,11 +351,13 @@ namespace realm { } results where(std::function &)> &&fn) { + static_assert(sizeof(managed), "Must declare schema for T"); auto schema = m_realm->schema().find(managed::schema.name); - auto table_ref = m_obj->get_target_table(m_key); - auto builder = internal::bridge::query(table_ref); - auto q = realm::query>(builder, std::move(schema), *m_realm); - auto full_query = fn(q).q; + auto group = m_realm->read_group(); + auto table_ref = group.get_table(schema.table_key()); + rbool query = rbool(internal::bridge::query(table_ref)); + auto query_object = managed::prepare_for_query(*m_realm, &query); + auto full_query = fn(query_object).q; return results(internal::bridge::results(*m_realm, full_query)); } diff --git a/src/cpprealm/managed_mixed.hpp b/src/cpprealm/managed_mixed.hpp index 54bf07d0..18c474cf 100644 --- a/src/cpprealm/managed_mixed.hpp +++ b/src/cpprealm/managed_mixed.hpp @@ -79,37 +79,29 @@ namespace realm { //MARK: - comparison operators rbool operator==(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->mixed_equal(m_key, serialize(rhs)); } return detach() == rhs; } rbool operator!=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->mixed_not_equal(m_key, serialize(rhs)); } return detach() != rhs; } rbool operator==(const std::nullopt_t& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, rhs); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->mixed_equal(m_key, internal::bridge::mixed(std::monostate())); } return detach() == T(std::monostate()); } rbool operator!=(const std::nullopt_t& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, rhs); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->mixed_not_equal(m_key, internal::bridge::mixed(std::monostate())); } return detach() != T(std::monostate()); } diff --git a/src/cpprealm/managed_numeric.hpp b/src/cpprealm/managed_numeric.hpp index 4c985761..7350a614 100644 --- a/src/cpprealm/managed_numeric.hpp +++ b/src/cpprealm/managed_numeric.hpp @@ -46,60 +46,48 @@ namespace realm { template std::enable_if_t, rbool> operator==(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, (int64_t)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, (int64_t)rhs); } return serialize(detach()) == rhs; } template std::enable_if_t, rbool> operator!=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, (int64_t)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, (int64_t)rhs); } return serialize(detach()) != rhs; } template std::enable_if_t, rbool> operator>(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater(this->m_key, (int64_t)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->greater(m_key, (int64_t)rhs); } return serialize(detach()) > rhs; } template std::enable_if_t, rbool> operator<(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less(this->m_key, (int64_t)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->less(m_key, (int64_t)rhs); } return serialize(detach()) < rhs; } template std::enable_if_t, rbool> operator>=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater_equal(this->m_key, (int64_t)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->greater_equal(m_key, (int64_t)rhs); } return serialize(detach()) >= rhs; } template std::enable_if_t, rbool> operator<=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less_equal(this->m_key, (int64_t)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->less_equal(m_key, (int64_t)rhs); } return serialize(detach()) <= rhs; } @@ -173,60 +161,48 @@ namespace realm { template std::enable_if_t< std::disjunction_v, std::is_floating_point>, rbool> operator==(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, (double)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, (double)rhs); } return serialize(detach()) == rhs; } template std::enable_if_t< std::disjunction_v, std::is_floating_point>, rbool> operator!=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, (double)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, (double)rhs); } return serialize(detach()) != rhs; } template std::enable_if_t< std::disjunction_v, std::is_floating_point>, rbool> operator>(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater(this->m_key, (double)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->greater(m_key, (double)rhs); } return serialize(detach()) > rhs; } template std::enable_if_t< std::disjunction_v, std::is_floating_point>, rbool> operator<(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less(this->m_key, (double)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->less(m_key, (double)rhs); } return serialize(detach()) < rhs; } template std::enable_if_t< std::disjunction_v, std::is_floating_point>, rbool> operator>=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater_equal(this->m_key, (double)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->greater_equal(m_key, (double)rhs); } return serialize(detach()) >= rhs; } template std::enable_if_t< std::disjunction_v, std::is_floating_point>, rbool> operator<=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less_equal(this->m_key, (double)rhs); - return rbool(std::move(query)); + if (this->m_rbool_query) { + return this->m_rbool_query->less_equal(m_key, (double)rhs); } return serialize(detach()) <= rhs; } @@ -436,50 +412,38 @@ CPP_REALM_MANAGED_OPTIONAL_NUMERIC(double); //MARK: - comparison operators rbool operator==(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, serialize(rhs)); } return detach() == rhs; } rbool operator!=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, serialize(rhs)); } return detach() != rhs; } rbool operator>(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->greater(m_key, serialize(rhs)); } return detach() > rhs; } rbool operator<(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->greater(m_key, serialize(rhs)); } return detach() < rhs; } rbool operator>=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->greater_equal(m_key, serialize(rhs)); } return detach() >= rhs; } rbool operator<=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->less_equal(m_key, serialize(rhs)); } return detach() <= rhs; } @@ -522,58 +486,38 @@ CPP_REALM_MANAGED_OPTIONAL_NUMERIC(double); //MARK: - comparison operators rbool operator==(const std::optional& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - if (auto r = rhs) { - query.equal(this->m_key, serialize(*r)); - } else { - query.equal(this->m_key, std::nullopt); - } - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, serialize(rhs)); } return detach() == rhs; } rbool operator!=(const std::optional& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - if (auto r = rhs) { - query.not_equal(this->m_key, serialize(*r)); - } else { - query.not_equal(this->m_key, std::nullopt); - } - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, serialize(rhs)); } return detach() != rhs; } rbool operator>(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->greater(m_key, rhs); } return detach() > rhs; } rbool operator<(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->less(m_key, rhs); } return detach() < rhs; } rbool operator>=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.greater_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->greater_equal(m_key, rhs); } return detach() >= rhs; } rbool operator<=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.less_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->less_equal(m_key, rhs); } return detach() <= rhs; } diff --git a/src/cpprealm/managed_primary_key.cpp b/src/cpprealm/managed_primary_key.cpp index 2ffcf8e7..c307b11b 100644 --- a/src/cpprealm/managed_primary_key.cpp +++ b/src/cpprealm/managed_primary_key.cpp @@ -4,10 +4,8 @@ namespace realm { #define __cpprealm_build_pk_query(op, name, type, rhs_type) \ rbool managed>::operator op(const rhs_type& rhs) const noexcept { \ - if (this->should_detect_usage_for_queries) { \ - auto query = internal::bridge::query(this->query->get_table()); \ - query.name(this->m_key, serialize(rhs)); \ - return query; \ + if (this->m_rbool_query) { \ + return this->m_rbool_query->name(m_key, rhs); \ } \ return serialize(detach().value) op serialize(rhs); \ } \ @@ -15,10 +13,8 @@ namespace realm { // Int needs to be cast to int64_t #define __cpprealm_build_int_pk_query(op, name, type, rhs_type, cast) \ rbool managed>::operator op(const rhs_type& rhs) const noexcept { \ - if (this->should_detect_usage_for_queries) { \ - auto query = internal::bridge::query(this->query->get_table()); \ - query.name(this->m_key, serialize((cast)rhs)); \ - return query; \ + if (this->m_rbool_query) { \ + return this->m_rbool_query->name(m_key, serialize((cast)rhs)); \ } \ return serialize(detach().value) op serialize((cast)rhs); \ } \ @@ -47,37 +43,29 @@ namespace realm { __cpprealm_build_pk_query(!=, not_equal, realm::object_id, realm::object_id) rbool managed>::operator ==(const char* rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, serialize(std::string(rhs))); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, std::string(rhs)); } return serialize(detach().value) == serialize(std::string(rhs)); } rbool managed>::operator !=(const char* rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, serialize(std::string(rhs))); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, std::string(rhs)); } return serialize(detach().value) != serialize(std::string(rhs)); } rbool managed>>::operator ==(const char* rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, serialize(std::string(rhs))); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, std::string(rhs)); } return serialize(detach().value) == serialize(std::string(rhs)); } rbool managed>>::operator !=(const char* rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, serialize(std::string(rhs))); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, std::string(rhs)); } return serialize(detach().value) != serialize(std::string(rhs)); } @@ -96,14 +84,8 @@ namespace realm { #define __cpprealm_build_optional_pk_query(op, name, type, rhs_type) \ rbool managed>>::operator op(const rhs_type& rhs) const noexcept { \ - if (this->should_detect_usage_for_queries) { \ - auto query = internal::bridge::query(this->query->get_table()); \ - if (auto r = serialize(rhs)) { \ - query.name(this->m_key, *r); \ - } else { \ - query.name(this->m_key, std::nullopt); \ - } \ - return query; \ + if (this->m_rbool_query) { \ + return this->m_rbool_query->name(m_key, rhs); \ } \ return serialize(detach()) op serialize(rhs); \ } \ diff --git a/src/cpprealm/managed_primary_key.hpp b/src/cpprealm/managed_primary_key.hpp index 2de9a0f4..09717103 100644 --- a/src/cpprealm/managed_primary_key.hpp +++ b/src/cpprealm/managed_primary_key.hpp @@ -19,6 +19,7 @@ #ifndef CPPREALM_MANAGED_PRIMARY_KEY_HPP #define CPPREALM_MANAGED_PRIMARY_KEY_HPP +#include #include namespace realm { @@ -296,18 +297,14 @@ namespace realm { } rbool operator==(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, serialize(rhs)); } return serialize(detach().value) == serialize(rhs); } rbool operator!=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, serialize(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, serialize(rhs)); } return serialize(detach().value) != serialize(rhs); } @@ -369,26 +366,14 @@ namespace realm { } rbool operator==(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - if (auto r = serialize(rhs)) { - query.equal(this->m_key, *r); - } else { - query.equal(this->m_key, std::nullopt); - } - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, serialize(rhs)); } return serialize(detach().value) == serialize(rhs); } rbool operator!=(const T& rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - if (auto r = serialize(rhs)) { - query.not_equal(this->m_key, *r); - } else { - query.not_equal(this->m_key, std::nullopt); - } - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, serialize(rhs)); } return serialize(detach().value) != serialize(rhs); } diff --git a/src/cpprealm/managed_string.cpp b/src/cpprealm/managed_string.cpp index ef5c4778..36072225 100644 --- a/src/cpprealm/managed_string.cpp +++ b/src/cpprealm/managed_string.cpp @@ -99,37 +99,29 @@ namespace realm { }; rbool managed_string::operator==(const char* rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, std::string(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, std::string(rhs)); } return detach() == rhs; } rbool managed_string::operator!=(const char* rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.not_equal(this->m_key, std::string(rhs)); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->not_equal(m_key, std::string(rhs)); } return detach() != rhs; } - rbool managed_string::contains(const std::string &rhs) const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.contains(this->m_key, std::string(rhs)); - return query; + rbool managed_string::contains(const std::string &rhs, bool case_sensitive) const noexcept { + if (this->m_rbool_query) { + return this->m_rbool_query->contains(m_key, std::string(rhs), case_sensitive); } return detach().find(rhs) != realm::not_in_collection; } rbool managed_string::empty() const noexcept { - if (this->should_detect_usage_for_queries) { - auto query = internal::bridge::query(this->query->get_table()); - query.equal(this->m_key, std::string()); - return query; + if (this->m_rbool_query) { + return this->m_rbool_query->equal(m_key, std::string()); } else { return detach().empty(); } diff --git a/src/cpprealm/managed_string.hpp b/src/cpprealm/managed_string.hpp index 9d9cab51..0a158306 100644 --- a/src/cpprealm/managed_string.hpp +++ b/src/cpprealm/managed_string.hpp @@ -118,7 +118,7 @@ namespace realm { rbool operator==(const char* rhs) const noexcept; rbool operator!=(const std::string& rhs) const noexcept; rbool operator!=(const char* rhs) const noexcept; - rbool contains(const std::string &s) const noexcept; + rbool contains(const std::string &s, bool case_sensitive = true) const noexcept; rbool empty() const noexcept; private: friend struct char_reference; diff --git a/src/cpprealm/rbool.hpp b/src/cpprealm/rbool.hpp index 6febca2b..de26bf6a 100644 --- a/src/cpprealm/rbool.hpp +++ b/src/cpprealm/rbool.hpp @@ -19,11 +19,11 @@ #ifndef CPPREALM_RBOOL_HPP #define CPPREALM_RBOOL_HPP -#include -#include - #include +#include +#include #include +#include namespace realm { template @@ -35,14 +35,163 @@ namespace realm { class rbool { bool is_for_queries = false; + std::optional m_link_chain; + internal::bridge::table m_table; + friend rbool operator&&(const rbool &lhs, const rbool &rhs); template friend struct results; friend rbool operator||(const rbool &lhs, const rbool &rhs); - public: + + rbool& add_link_chain(internal::bridge::realm* realm, + const internal::bridge::col_key& col_key) { + if (m_link_chain) { + m_link_chain->link(col_key); + } else { + m_link_chain = m_table.get_link(col_key); + } + return *this; + } + +#define define_query(type, comparison) \ + rbool& comparison(const internal::bridge::col_key& col_key, const std::optional& rhs) { \ + if (auto lc = m_link_chain) { \ + q = lc->column(col_key).comparison(rhs); \ + m_link_chain = std::nullopt; \ + } else { \ + if (rhs) { \ + q = internal::bridge::query(q.get_table()).comparison(col_key, *rhs); \ + } else { \ + q = internal::bridge::query(q.get_table()).comparison(col_key, std::nullopt); \ + } \ + } \ + return *this; \ + } \ + rbool& comparison(const internal::bridge::col_key& col_key, const type& rhs) { \ + if (auto lc = m_link_chain) { \ + q = lc->column(col_key).comparison(std::optional(rhs)); \ + m_link_chain = std::nullopt; \ + } else { \ + q = internal::bridge::query(q.get_table()).comparison(col_key, rhs); \ + } \ + return *this; \ + } + +#define define_numeric_query(type, comparison) \ + rbool& comparison(const internal::bridge::col_key& col_key, const type& rhs) { \ + if (auto lc = m_link_chain) { \ + q = lc->column(col_key).comparison(::realm::serialize(std::optional(rhs))); \ + m_link_chain = std::nullopt; \ + } else { \ + q = internal::bridge::query(q.get_table()).comparison(col_key, rhs); \ + } \ + return *this; \ + } + + define_query(std::string, equal) + define_query(std::string, not_equal) + + rbool& contains(const internal::bridge::col_key& col_key, const std::string& rhs, bool case_sensitive = true) { + if (auto lc = m_link_chain) { + q = lc->column(col_key).contains(::realm::serialize(std::optional(rhs))); + m_link_chain = std::nullopt; + } else { + q = internal::bridge::query(q.get_table()).contains(col_key, rhs); + } + return *this; + } + + define_query(int64_t, equal) + define_query(int64_t, not_equal) + define_numeric_query(int64_t, greater) + define_numeric_query(int64_t, less) + define_numeric_query(int64_t, greater_equal) + define_numeric_query(int64_t, less_equal) + + define_query(bool, equal) + define_query(bool, not_equal) + + define_query(double, equal) + define_query(double, not_equal) + define_numeric_query(double, greater) + define_numeric_query(double, less) + define_numeric_query(double, greater_equal) + define_numeric_query(double, less_equal) + + define_query(std::vector, equal) + define_query(std::vector, not_equal) + + define_query(std::chrono::time_point, equal) + define_query(std::chrono::time_point, not_equal) + define_numeric_query(std::chrono::time_point, greater) + define_numeric_query(std::chrono::time_point, less) + define_numeric_query(std::chrono::time_point, greater_equal) + define_numeric_query(std::chrono::time_point, less_equal) + + define_query(uuid, equal) + define_query(uuid, not_equal) + + define_query(object_id, equal) + define_query(object_id, not_equal) + + define_query(decimal128, equal) + define_query(decimal128, not_equal) + define_numeric_query(decimal128, greater) + define_numeric_query(decimal128, less) + define_numeric_query(decimal128, greater_equal) + define_numeric_query(decimal128, less_equal) + + rbool& mixed_equal(const internal::bridge::col_key& col_key, const internal::bridge::mixed& rhs) { + if (auto lc = m_link_chain) { + q = lc->column(col_key).mixed_equal(rhs); + m_link_chain = std::nullopt; + } else { + q.equal(col_key, rhs); + } + return *this; + } + + rbool& mixed_not_equal(const internal::bridge::col_key& col_key, const internal::bridge::mixed& rhs) { + if (auto lc = m_link_chain) { + q = lc->column_mixed(col_key).mixed_not_equal(rhs); + m_link_chain = std::nullopt; + } else { + q.not_equal(col_key, rhs); + } + return *this; + } + + rbool& link_equal(const internal::bridge::col_key& col_key, const std::optional& rhs) { + if (auto lc = m_link_chain) { + q = lc->column(col_key).equal(rhs); + m_link_chain = std::nullopt; + } else { + if (rhs) { + q.links_to(col_key, *rhs); + } else { + q.links_to(col_key, internal::bridge::obj()); + } + } + return *this; + } + + rbool& link_not_equal(const internal::bridge::col_key& col_key, const std::optional& rhs) { + if (auto lc = m_link_chain) { + q = lc->column(col_key).not_equal(rhs); + m_link_chain = std::nullopt; + } else { + if (rhs) { + q.not_links_to(col_key, *rhs); + } else { + q.not_links_to(col_key, internal::bridge::obj()); + } + } + return *this; + } + ~rbool() { if (is_for_queries) q.~query(); @@ -52,11 +201,7 @@ namespace realm { } rbool operator!() const { if (is_for_queries) { -#ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES - new(&q) internal::bridge::query(q.negate()); -#else - q = internal::bridge::query(q.negate()); -#endif + q.negate(); return *this; } return !b; @@ -66,7 +211,9 @@ namespace realm { mutable internal::bridge::query q; }; - rbool(internal::bridge::query &&q) : q(q), is_for_queries(true) {} + rbool(internal::bridge::query &&q) : q(q), is_for_queries(true) { + m_table = q.get_table(); + } rbool(bool b) : b(b) {} rbool(const rbool &r) { if (r.is_for_queries) { diff --git a/src/cpprealm/results.hpp b/src/cpprealm/results.hpp index 351f0dae..0964dee1 100644 --- a/src/cpprealm/results.hpp +++ b/src/cpprealm/results.hpp @@ -24,12 +24,11 @@ #include #include #include -#include #include #include +#include namespace realm { - class rbool; struct mutable_sync_subscription_set; } @@ -44,45 +43,6 @@ namespace realm { template struct results_common_base; - - template - struct query : public T { - private: - template - void set_managed(V &prop, const internal::bridge::col_key &column_key, internal::bridge::realm& r) { - new(&prop.m_key) internal::bridge::col_key(column_key); - prop.m_realm = &r; - } - - template - constexpr auto - prepare_for_query(internal::bridge::query &query, internal::bridge::object_schema &schema, - internal::bridge::realm& r, P property) { - if constexpr (N + 1 == std::tuple_size_v) { - (this->*property).prepare_for_query(query); - set_managed((this->*property), schema.property_for_name(T::schema.names[N]).column_key(), r); - return; - } else { - (this->*property).prepare_for_query(query); - set_managed((this->*property), schema.property_for_name(T::schema.names[N]).column_key(), r); - return prepare_for_query(query, schema, r, std::get(T::managed_pointers() )); - } - } - - query(internal::bridge::query &query, internal::bridge::object_schema &&schema, internal::bridge::realm& r) { - prepare_for_query<0>(query, schema, r, std::get<0>(T::managed_pointers())); - } - template - friend struct ::realm::results; - template - friend struct ::realm::results_base; - template - friend struct ::realm::results_common_base; - template - friend struct ::realm::managed; - friend struct ::realm::mutable_sync_subscription_set; - }; - template struct results_common_base { explicit results_common_base(internal::bridge::results &&parent) @@ -124,9 +84,9 @@ namespace realm { auto schema = realm.schema().find(managed::schema.name); auto group = realm.read_group(); auto table_ref = group.get_table(schema.table_key()); - auto builder = internal::bridge::query(table_ref); - auto q = realm::query>(builder, std::move(schema), realm); - auto full_query = fn(q).q; + rbool query = rbool(internal::bridge::query(table_ref)); + auto query_object = managed::prepare_for_query(realm, &query); + auto full_query = fn(query_object).q; return Derived(internal::bridge::results(m_parent.get_realm(), full_query)); } diff --git a/tests/admin_utils.cpp b/tests/admin_utils.cpp index 63d35bac..f5d353ca 100644 --- a/tests/admin_utils.cpp +++ b/tests/admin_utils.cpp @@ -159,10 +159,10 @@ std::string Admin::Session::create_app(bson::BsonArray queryable_fields, std::st bson::BsonDocument mongodb_service_config; std::string mongodb_service_type; if (m_cluster_name) { - mongodb_service_config["clusterName"] = *m_cluster_name; + mongodb_service_config.append("clusterName", *m_cluster_name); mongodb_service_type = "mongodb-atlas"; } else { - mongodb_service_config["uri"] = "mongodb://localhost:26000"; + mongodb_service_config.append("uri", "mongodb://localhost:26000"); mongodb_service_type = "mongodb"; } diff --git a/tests/db/object_tests.cpp b/tests/db/object_tests.cpp index ba09cf4b..50e5cb09 100644 --- a/tests/db/object_tests.cpp +++ b/tests/db/object_tests.cpp @@ -377,7 +377,7 @@ namespace realm { return db.add(std::move(obj)); }); - managed AllTypesObject_res = db.objects()[0]; + managed allTypesObject_res = db.objects()[0]; managed allTypeObjectLink = db.objects().where([](auto& o) { return o._id == 1; })[0]; @@ -479,8 +479,8 @@ namespace realm { CHECK(results_obj.opt_obj_col == allTypeObjectLink); CHECK(results_obj.opt_obj_col != allTypeObjectLink2); - CHECK(results_obj.opt_embedded_obj_col == AllTypesObject_res.opt_embedded_obj_col); - CHECK(!(results_obj.opt_embedded_obj_col != managed_obj.opt_embedded_obj_col)); + CHECK(results_obj.opt_embedded_obj_col == allTypesObject_res.opt_embedded_obj_col); + CHECK(results_obj.opt_embedded_obj_col != managed_obj.opt_embedded_obj_col); CHECK(results_obj.list_int_col[0] == 1); CHECK(results_obj.list_double_col[0] == 1.23); @@ -495,7 +495,7 @@ namespace realm { CHECK(results_obj.list_obj_col[0]->str_col == "link object 2"); CHECK(results_obj.list_obj_col[0] == allTypeObjectLink2); CHECK(results_obj.opt_obj_col->str_link_col->str_col == "string col link"); - CHECK(results_obj.list_embedded_obj_col[0] == AllTypesObject_res.list_embedded_obj_col[0]); + CHECK(results_obj.list_embedded_obj_col[0] == allTypesObject_res.list_embedded_obj_col[0]); CHECK(results_obj.list_embedded_obj_col[0] != managed_obj.opt_embedded_obj_col); CHECK(results_obj.map_int_col["foo"] == 1); @@ -509,7 +509,7 @@ namespace realm { CHECK(results_obj.map_decimal_col["foo"] == decimal); CHECK(results_obj.map_mixed_col["foo"] == realm::mixed("bar")); CHECK(results_obj.map_link_col["foo"] == other_obj2); - CHECK(results_obj.map_embedded_col["foo"]->str_col == AllTypesObject_res.map_embedded_col["foo"]->str_col); + CHECK(results_obj.map_embedded_col["foo"]->str_col == allTypesObject_res.map_embedded_col["foo"]->str_col); CHECK(results_obj.map_embedded_col["foo"]->str_col != managed_obj.opt_embedded_obj_col->str_col); } diff --git a/tests/db/query_tests.cpp b/tests/db/query_tests.cpp index 027c1408..32ac55ee 100644 --- a/tests/db/query_tests.cpp +++ b/tests/db/query_tests.cpp @@ -256,24 +256,34 @@ namespace realm { SECTION("link column") { auto realm = db(std::move(config)); - auto obj = AllTypesObject(); - auto obj_link = AllTypesObjectLink(); - obj_link.str_col = "foo"; - auto obj_link2 = StringObject(); - obj_link2.str_col = "bar"; + auto create_obj = [&](int64_t pk) { + auto obj = AllTypesObject(); + obj._id = pk; + obj.str_col = "root obj"; + auto obj_link = AllTypesObjectLink(); + obj_link._id = pk; + obj_link.str_col = "foo"; + auto obj_link2 = StringObject(); + obj_link2._id = pk; + obj_link2.str_col = "bar"; + + obj.opt_obj_col = &obj_link; + obj_link.str_link_col = &obj_link2; - obj.opt_obj_col = &obj_link; - obj_link.str_link_col = &obj_link2; + return realm.write([&]() { + return realm.add(std::move(obj)); + }); + }; - auto managed_obj = realm.write([&]() { - return realm.add(std::move(obj)); - }); + auto managed_obj = create_obj(0); + auto managed_obj2 = create_obj(1); + auto managed_obj3 = create_obj(2); auto res = realm.objects().where([](auto &obj) { return obj.opt_obj_col->str_col == "foo"; }); - CHECK(res.size() == 1); - CHECK(query_string_results_size(AllTypesObject, "opt_obj_col.str_col == $0", {std::string("foo")}) == 1); + CHECK(res.size() == 3); + CHECK(query_string_results_size(AllTypesObject, "opt_obj_col.str_col == $0", {std::string("foo")}) == 3); res = realm.objects().where([](auto &obj) { return obj.opt_obj_col->str_col == "bar"; @@ -284,20 +294,40 @@ namespace realm { res = realm.objects().where([](auto &obj) { return obj.opt_obj_col->str_col != "bar"; }); - CHECK(res.size() == 1); - CHECK(query_string_results_size(AllTypesObject, "str_col != $0", {std::string("bar")}) == 1); + CHECK(res.size() == 3); + CHECK(query_string_results_size(AllTypesObject, "str_col != $0", {std::string("bar")}) == 3); res = realm.objects().where([](auto &obj) { return obj.opt_obj_col->str_link_col->str_col == "bar"; }); - CHECK(res.size() == 1); - CHECK(query_string_results_size(AllTypesObject, "opt_obj_col.str_link_col.str_col == $0", {std::string("bar")}) == 1); + CHECK(res.size() == 3); + CHECK(query_string_results_size(AllTypesObject, "opt_obj_col.str_link_col.str_col == $0", {std::string("bar")}) == 3); res = realm.objects().where([](auto &obj) { return obj.opt_obj_col->str_link_col->str_col != "bar"; }); CHECK(res.size() == 0); CHECK(query_string_results_size(AllTypesObject, "opt_obj_col.str_link_col.str_col != $0", {std::string("bar")}) == 0); + + res = realm.objects().where([&](auto &obj) { + return obj.opt_obj_col == managed_obj.opt_obj_col; + }); + CHECK(res.size() == 1); + + res = realm.objects().where([](auto &obj) { + return obj.opt_obj_col == std::nullptr_t(); + }); + CHECK(res.size() == 0); + + res = realm.objects().where([&](auto &obj) { + return obj.opt_obj_col != managed_obj.opt_obj_col; + }); + CHECK(res.size() == 2); + + res = realm.objects().where([](auto &obj) { + return obj.opt_obj_col != std::nullptr_t(); + }); + CHECK(res.size() == 3); } } } \ No newline at end of file