diff --git a/.gitignore b/.gitignore
index 86244e6d9..e7d5d1eb1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,5 +10,5 @@ Package.resolved
examples/*.pro.user
docs/html
docs/latex
-.idea
-realm-core/src/realm/parser/generated
\ No newline at end of file
+.idea/
+realm-core/src/realm/parser/generated/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b81b..000000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index b3988e494..000000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-RealmCxx
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 24025e857..000000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index 79ee123c2..000000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/deployment.xml b/.idea/deployment.xml
deleted file mode 100644
index aa03c8f8c..000000000
--- a/.idea/deployment.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 79b3c9483..000000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index f3cff116d..000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/realm-cpp-sdk.iml b/.idea/realm-cpp-sdk.iml
deleted file mode 100644
index f08604bb6..000000000
--- a/.idea/realm-cpp-sdk.iml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 1f05e07a9..000000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e437afc15..b30336ccb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-X.Y.Z Release notes (YYYY-MM-DD)
+NEXT RELEASE Release notes (YYYY-MM-DD)
=============================================================
### Fixed
@@ -8,6 +8,8 @@ X.Y.Z Release notes (YYYY-MM-DD)
* Add `realm::default_scheduler::set_default_factory(std::function()>&& factory_fn)` for generating a default scheduler.
Set your scheduler factory before instantiating a `realm::db_config`.
* Add `realm::default_scheduler::make_default()` which generates a platform default scheduler if `realm::default_scheduler::set_default_factory` is not set.
+* Add `managed::to_json(std::ostream&)` which allows managed objects to be printed as json.
+* Add `rbool::truepredicate()` and `rbool::falsepredicate()` expressions for type safe queries.
### Compatibility
* Fileformat: Generates files with format v24. Reads and automatically upgrade from fileformat v10.
diff --git a/include/cpprealm/internal/bridge/obj.hpp b/include/cpprealm/internal/bridge/obj.hpp
index 64166b725..c2b256f6c 100644
--- a/include/cpprealm/internal/bridge/obj.hpp
+++ b/include/cpprealm/internal/bridge/obj.hpp
@@ -226,7 +226,7 @@ namespace realm::internal::bridge {
void set_null(const col_key&);
obj create_and_set_linked_object(const col_key&);
table_view get_backlink_view(table, col_key);
-
+ void to_json(std::ostream& out) const noexcept;
private:
inline const Obj* get_obj() const;
inline Obj* get_obj();
diff --git a/include/cpprealm/internal/bridge/query.hpp b/include/cpprealm/internal/bridge/query.hpp
index f19141e9b..569c91ba5 100644
--- a/include/cpprealm/internal/bridge/query.hpp
+++ b/include/cpprealm/internal/bridge/query.hpp
@@ -232,6 +232,9 @@ namespace realm::internal::bridge {
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);
+ // Expressions
+ static query falsepredicate();
+
std::string description() const;
private:
inline Query* get_query();
@@ -243,11 +246,6 @@ namespace realm::internal::bridge {
};
- template
- using QFn = query& (query::*)(col_key, T);
- template
- using QFnCS = query& (query::*)(col_key, T, bool);
-
query operator || (const query& lhs, const query& rhs);
}
diff --git a/include/cpprealm/macros.hpp b/include/cpprealm/macros.hpp
index 059d11c65..dfb8b6034 100644
--- a/include/cpprealm/macros.hpp
+++ b/include/cpprealm/macros.hpp
@@ -544,7 +544,9 @@ rbool managed>::operator op(const std::optional& rhs)
db get_realm() { \
return db(m_realm); \
} \
- bool operator ==(const managed& other) const { \
+ bool operator ==(const managed& other) const { \
+ if (m_rbool_query != nullptr) \
+ throw std::runtime_error("This comparison operator is not valid inside of `where`"); \
auto& a = m_obj; \
auto& b = other.m_obj; \
if (m_realm != other.m_realm) { \
@@ -554,6 +556,8 @@ rbool managed>::operator op(const std::optional& rhs)
&& a.get_key() == b.get_key(); \
} \
bool operator ==(const managed& other) const { \
+ if (m_rbool_query != nullptr) \
+ throw std::runtime_error("This comparison operator is not valid inside of `where`"); \
auto& a = m_obj; \
auto& b = other.m_obj; \
if (m_realm != other->m_realm) { \
@@ -571,6 +575,9 @@ rbool managed>::operator op(const std::optional& rhs)
bool operator < (const managed& rhs) const { \
return m_obj.get_key() < rhs.m_obj.get_key(); \
} \
+ void to_json(std::ostream& out) const noexcept { \
+ m_obj.to_json(out); \
+ } \
private: \
internal::bridge::obj m_obj; \
internal::bridge::realm m_realm; \
@@ -579,6 +586,8 @@ rbool managed>::operator op(const std::optional& rhs)
template friend struct managed; \
template friend struct box; \
template friend struct ::realm::thread_safe_reference; \
+ template friend rbool* ::realm::internal::get_rbool(const T&); \
+ \
}; \
struct meta_schema_##cls { \
meta_schema_##cls() { \
@@ -590,4 +599,15 @@ rbool managed>::operator op(const std::optional& rhs)
}; \
static inline meta_schema_##cls _meta_schema_##cls{};
+namespace realm::internal {
+ /*
+ * Helper method for extracting the private `m_rbool_query`
+ * property on a managed object.
+ */
+ template
+ rbool* get_rbool(const T& o) {
+ return o.m_rbool_query;
+ }
+}
+
#endif //CPPREALM_MACROS_HPP
diff --git a/include/cpprealm/rbool.hpp b/include/cpprealm/rbool.hpp
index 6b2c92f83..ecfe39c85 100644
--- a/include/cpprealm/rbool.hpp
+++ b/include/cpprealm/rbool.hpp
@@ -38,14 +38,11 @@ namespace realm {
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);
friend rbool operator||(const rbool &lhs, const rbool &rhs);
public:
-
rbool& add_link_chain(const internal::bridge::col_key& col_key) {
if (m_link_chain) {
m_link_chain->link(col_key);
@@ -237,6 +234,29 @@ namespace realm {
}
return lhs.b && rhs.b;
}
+
+ /// Return all objects from a collection.
+ template
+ inline rbool truepredicate(const T& o) {
+ // An empty query returns all results and one way to indicate this
+ // is to serialise TRUEPREDICATE which is functionally equivalent
+ rbool* rb = internal::get_rbool(o);
+ if (rb == nullptr)
+ throw std::runtime_error("Managed object is not used in a query context");
+ auto table = rb->q.get_table();
+ return rbool(table);
+ }
+
+/// Return no objects from a collection.
+ template
+ inline rbool falsepredicate(const T& o) {
+ rbool* rb = internal::get_rbool(o);
+ if (rb == nullptr)
+ throw std::runtime_error("Managed object is not used in a query context");
+ auto table = rb->q.get_table();
+ auto q = internal::bridge::query(table).and_query(internal::bridge::query(table).falsepredicate());
+ return rbool(std::move(q));
+ }
}
#endif //CPPREALM_RBOOL_HPP
diff --git a/src/cpprealm/internal/bridge/obj.cpp b/src/cpprealm/internal/bridge/obj.cpp
index 4e8d98395..c6c5033be 100644
--- a/src/cpprealm/internal/bridge/obj.cpp
+++ b/src/cpprealm/internal/bridge/obj.cpp
@@ -406,6 +406,10 @@ namespace realm::internal::bridge {
table_view obj::get_backlink_view(table table, col_key col_key) {
return get_obj()->get_backlink_view(table, col_key);
}
+
+ void obj::to_json(std::ostream& out) const noexcept {
+ return get_obj()->to_json(out);
+ }
}
std::string realm::internal::bridge::table_name_for_object_type(const std::string &v) {
diff --git a/src/cpprealm/internal/bridge/query.cpp b/src/cpprealm/internal/bridge/query.cpp
index 2252de805..4500300c9 100644
--- a/src/cpprealm/internal/bridge/query.cpp
+++ b/src/cpprealm/internal/bridge/query.cpp
@@ -595,6 +595,10 @@ namespace realm::internal::bridge {
return *this;
}
+ query query::falsepredicate() {
+ return query(Query(std::make_unique()));
+ }
+
std::string query::description() const {
#ifdef CPPREALM_HAVE_GENERATED_BRIDGE_TYPES
return reinterpret_cast(&m_query)->get_description();
diff --git a/tests/db/object_tests.cpp b/tests/db/object_tests.cpp
index aae60ae65..b1b3d1911 100644
--- a/tests/db/object_tests.cpp
+++ b/tests/db/object_tests.cpp
@@ -1,6 +1,8 @@
#include "../main.hpp"
#include "test_objects.hpp"
+#include
+
namespace realm {
enum class PrimaryKeyEnum {
@@ -1035,6 +1037,22 @@ namespace realm {
CHECK(realm.objects().size() == 1);
}
+ SECTION("to_json") {
+ StringObject str_obj;
+ str_obj.str_col = "test";
+ str_obj._id = 123;
+ auto realm = db(std::move(config));
+
+ auto managed_obj = realm.write([&](){
+ return realm.add(std::move(str_obj));
+ });
+
+ std::stringstream ss;
+ managed_obj.to_json(ss);
+ auto json_str = ss.str();
+ CHECK(json_str == "{\"_id\":123,\"str_col\":\"test\"}");
+ }
+
static_assert(!std::is_constructible_v::ref_type>, "Default constructor is private.");
static_assert(!std::is_constructible_v>, "Default constructor is private.");
static_assert(!std::is_constructible_v>, "Default constructor is private.");
diff --git a/tests/db/query_tests.cpp b/tests/db/query_tests.cpp
index 32ac55ee3..4abe4b5cc 100644
--- a/tests/db/query_tests.cpp
+++ b/tests/db/query_tests.cpp
@@ -329,5 +329,84 @@ namespace realm {
});
CHECK(res.size() == 3);
}
+
+ SECTION("TRUEPREDICATE_FALSEPREDICATE") {
+ auto realm = db(std::move(config));
+
+ 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;
+
+ return 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& o) {
+ return truepredicate(o);
+ });
+ CHECK(res.size() == 3);
+
+ res = realm.objects().where([](auto& o) {
+ return falsepredicate(o);
+ });
+ CHECK(res.size() == 0);
+ }
+
+ SECTION("sub results") {
+ auto realm = db(std::move(config));
+
+ 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;
+
+ return 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& o) {
+ return o._id > 0;
+ });
+ CHECK(res.size() == 2);
+
+ res = res.where([](auto& o) {
+ return o._id > 1;
+ });
+ CHECK(res.size() == 1);
+
+ res = res.where([](auto& o) {
+ return truepredicate(o);
+ });
+ CHECK(res.size() == 3);
+ }
}
-}
\ No newline at end of file
+}