Skip to content

Commit f2e65a1

Browse files
authored
instead of throwing an exception on ill-formatted geospatial data, queries will now ignore those objects (#6989)
1 parent b37bbdd commit f2e65a1

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
([PR #6837](https://github.com/realm/realm-core/pull/6837), since v10.0.0)
1515
* Reading existing logged-in users on app startup from the sync metadata Realm performed three no-op writes per user on the metadata Realm ([PR #6837](https://github.com/realm/realm-core/pull/6837), since v10.0.0).
1616
* If a user was logged out while an access token refresh was in progress, the refresh completing would mark the user as logged in again and the user would be in an inconsistent state ([PR #6837](https://github.com/realm/realm-core/pull/6837), since v10.0.0).
17+
* If querying over a geospatial dataset that had some objects with a type property set to something other than 'Point' (case insensitive) an exception would have been thrown. Instead of disrupting the query, those objects are now just ignored. ([PR 6989](https://github.com/realm/realm-core/issues/6989), since the introduction of geospatial)
1718
* The Swift package failed to link required libraries when building for macCatalyst.
1819

1920
### Breaking changes

src/realm/geospatial.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ std::optional<GeoPoint> Geospatial::point_from_obj(const Obj& obj, ColKey type_c
154154
}
155155

156156
if (!type_is_valid(obj.get<StringData>(type_col))) {
157-
throw IllegalOperation("The only Geospatial type currently supported is 'point'");
157+
return {}; // the only geospatial type currently supported is 'Point'
158158
}
159159

160160
Lst<double> coords = obj.get_list<double>(coords_col);
@@ -211,7 +211,9 @@ void Geospatial::assign_to(Obj& link) const
211211
return;
212212
}
213213
if (type != Type::Point) {
214-
throw IllegalOperation("The only Geospatial type currently supported for storage is 'point'");
214+
throw IllegalOperation(util::format("Attempting to store a '%1' in class '%2' but the only Geospatial type "
215+
"currently supported for storage is 'Point'",
216+
get_type_string(), link.get_table()->get_class_name()));
215217
}
216218
auto&& point = get<GeoPoint>();
217219
link.set(type_col, get_type_string());

test/test_query_geo.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,13 @@ TEST(Geospatial_Assignment)
112112

113113
Geospatial geo_box(GeoBox{GeoPoint{1.1, 2.2}, GeoPoint{3.3, 4.4}});
114114
CHECK(*GeoBox::from_polygon(geo_box.get<GeoBox>().to_polygon()) == geo_box.get<GeoBox>());
115-
std::string_view err_msg = "The only Geospatial type currently supported for storage is 'point'";
116-
CHECK_THROW_CONTAINING_MESSAGE(obj.set(location_column_key, geo_box), err_msg);
115+
std::string_view err_msg_box = "Attempting to store a 'Box' in class 'Location' but the only Geospatial type "
116+
"currently supported for storage is 'Point'";
117+
CHECK_THROW_CONTAINING_MESSAGE(obj.set(location_column_key, geo_box), err_msg_box);
117118
Geospatial geo_circle(GeoCircle{10, GeoPoint{1.1, 2.2}});
118-
CHECK_THROW_CONTAINING_MESSAGE(obj.set(location_column_key, geo_circle), err_msg);
119+
std::string_view err_msg_circle = "Attempting to store a 'Circle' in class 'Location' but the only Geospatial "
120+
"type currently supported for storage is 'Point'";
121+
CHECK_THROW_CONTAINING_MESSAGE(obj.set(location_column_key, geo_circle), err_msg_circle);
119122
}
120123

121124
TEST(Geospatial_invalid_format)
@@ -137,10 +140,31 @@ TEST(Geospatial_invalid_format)
137140
TEST(Query_GeoWithinBasics)
138141
{
139142
Group g;
140-
std::vector<Geospatial> data = {GeoPoint{-2, -1}, GeoPoint{-1, -2}, GeoPoint{0, 0},
141-
GeoPoint{0.5, 0.5}, GeoPoint{1, 1}, GeoPoint{2, 2}};
143+
std::vector<Geospatial> data = {GeoPoint{-2, -1}, GeoPoint{-1, -2}, GeoPoint{0, 0}, GeoPoint{0.5, 0.5},
144+
GeoPoint{1, 1}, GeoPoint{2, 2, 2}, GeoPoint()};
142145
TableRef table = setup_with_points(g, data);
143146
ColKey location_column_key = table->get_column_key("location");
147+
// an object with null link location
148+
table->create_object_with_primary_key(-42);
149+
// an object with a location that doesn't have properties set on the point
150+
Obj invalid_point = table->create_object_with_primary_key(-43);
151+
invalid_point.create_and_set_linked_object(location_column_key);
152+
// an object with the correct 'Point' but invalid coordinates
153+
Obj invalid_coords = table->create_object_with_primary_key(-44);
154+
Obj embedded_invalid = invalid_coords.create_and_set_linked_object(location_column_key);
155+
embedded_invalid.set(embedded_invalid.get_table()->get_column_key("type"), "Point");
156+
// an object with 4 elements in the coordinate list
157+
Obj excess_coords = table->create_object_with_primary_key(-44);
158+
Obj embedded_excess = excess_coords.create_and_set_linked_object(location_column_key);
159+
embedded_excess.set(embedded_excess.get_table()->get_column_key("type"), "Point");
160+
auto list = embedded_excess.get_list<double>(embedded_excess.get_table()->get_column_key("coordinates"));
161+
list.add(2);
162+
list.add(2);
163+
list.add(2);
164+
list.add(2);
165+
Geospatial geo_excess = excess_coords.get<Geospatial>(location_column_key);
166+
CHECK(geo_excess.is_valid() == Status::OK());
167+
144168
for (size_t i = 0; i < data.size(); ++i) {
145169
Obj obj = table->get_object_with_primary_key(int64_t(i));
146170
CHECK(obj);

0 commit comments

Comments
 (0)