diff --git a/src/realm/object-store/c_api/notifications.cpp b/src/realm/object-store/c_api/notifications.cpp index 057714267c5..d9e2909755d 100644 --- a/src/realm/object-store/c_api/notifications.cpp +++ b/src/realm/object-store/c_api/notifications.cpp @@ -88,21 +88,20 @@ static KeyPathArray create_key_path_array(const ObjectSchema& object_schema, con StringData property(path, p - path); path = p; if (!schema_at_index) { - auto found_schema = schema.find(prop->object_type); - if (found_schema != schema.end()) { - schema_at_index = &*found_schema; - } - else { - throw InvalidArgument( - util::format("Property '%1' in KeyPath '%2' is not a collection of objects or an object " - "reference, so it cannot be used as an intermediate keypath element.", - prop->public_name, *it)); - } + throw InvalidArgument( + util::format("Property '%1' in KeyPath '%2' is not a collection of objects or an object " + "reference, so it cannot be used as an intermediate keypath element.", + prop->public_name, *it)); } prop = schema_at_index->property_for_public_name(property); if (prop) { + if (prop->type == PropertyType::Object || prop->type == PropertyType::LinkingObjects) { + auto found_schema = schema.find(prop->object_type); + if (found_schema != schema.end()) { + schema_at_index = &*found_schema; + } + } resolved_key_path.emplace_back(schema_at_index->table_key, prop->column_key); - schema_at_index = nullptr; } else { throw InvalidArgument(util::format("Property '%1' in KeyPath '%2' is not a valid property in %3.", diff --git a/src/realm/object-store/object_store.cpp b/src/realm/object-store/object_store.cpp index 6c38f2d117c..4fcb9f4f5c1 100644 --- a/src/realm/object-store/object_store.cpp +++ b/src/realm/object-store/object_store.cpp @@ -942,6 +942,13 @@ void ObjectStore::set_schema_keys(Group const& group, Schema& schema) for (auto& property : object_schema.persisted_properties) { property.column_key = table->get_column_key(property.name); } + for (auto& property : object_schema.computed_properties) { + if (property.type == PropertyType::LinkingObjects) { + auto origin_table = ObjectStore::table_for_object_type(group, property.object_type); + auto origin_column_key = origin_table->get_column_key(property.link_origin_property_name); + property.column_key = origin_table->get_opposite_column(origin_column_key); + } + } } } diff --git a/test/object-store/c_api/c_api.cpp b/test/object-store/c_api/c_api.cpp index 8c9937ed5f5..173044e626b 100644 --- a/test/object-store/c_api/c_api.cpp +++ b/test/object-store/c_api/c_api.cpp @@ -2779,6 +2779,23 @@ TEST_CASE("C API - properties", "[c_api]") { REQUIRE(key_path_array); realm_release(key_path_array); } + SECTION("using backlink") { + const char* bar_strings[1] = {"linking_objects.public_int"}; + auto key_path_array = realm_create_key_path_array(realm, class_bar.key, 1, bar_strings); + REQUIRE(key_path_array); + auto token = cptr_checked(realm_list_add_notification_callback(bars.get(), &state, nullptr, + key_path_array, on_change)); + realm_release(key_path_array); + checked(realm_refresh(realm, nullptr)); + + state.called = false; + write([&]() { + checked(realm_set_value(obj1.get(), foo_int_key, rlm_int_val(999), false)); + }); + REQUIRE(state.called); + CHECK(!state.error); + CHECK(state.changes); + } SECTION("using invalid nesting") { const char* bar_strings[1] = {"doubles.age"}; auto key_path_array = realm_create_key_path_array(realm, class_bar.key, 1, bar_strings);