Skip to content

Commit 8c20d35

Browse files
committed
add query.findUnique()
1 parent 0e9082b commit 8c20d35

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

objectbox/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## latest
2+
3+
* Add `Query.findUnique()` to find a single object matching the query.
4+
15
## 1.1.1 (2021-07-09)
26

37
* Add support for `Query.param()` on linked entities.

objectbox/lib/src/native/query/query.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,32 @@ class Query<T> {
748748
return result;
749749
}
750750

751+
/// Finds the only object matching the query. Returns null if there are no
752+
/// results or throws if there are multiple objects matching.
753+
///
754+
/// Note: [offset] and [limit] are respected, if set. Because [limit] affects
755+
/// the number of matched objects, make sure you leave it at zero or set it
756+
/// higher than one, otherwise the check for non-unique result won't work.
757+
T? findUnique() {
758+
T? result;
759+
Exception? error;
760+
final visitor = dataVisitor((Pointer<Uint8> data, int size) {
761+
if (result == null) {
762+
result = _entity.objectFromFB(
763+
_store, InternalStoreAccess.reader(_store).access(data, size));
764+
} else {
765+
error = UniqueViolationException(
766+
'Query findUnique() matched more than one object');
767+
return false;
768+
}
769+
return true;
770+
});
771+
checkObx(C.query_visit(_ptr, visitor, nullptr));
772+
reachabilityFence(this);
773+
if (error != null) throw error!;
774+
return result;
775+
}
776+
751777
/// Finds Objects matching the query and returns their IDs.
752778
List<int> findIds() {
753779
final idArrayPtr = checkObxPtr(C.query_find_ids(_ptr), 'find ids');

objectbox/test/query_test.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,25 @@ void main() {
352352
q.close();
353353
});
354354

355+
test('.findUnique', () {
356+
box.put(TestEntity(tLong: 0));
357+
box.put(TestEntity(tString: 't1'));
358+
box.put(TestEntity(tString: 't2'));
359+
360+
var query = box.query(TestEntity_.tString.startsWith('t')).build();
361+
362+
expect(
363+
() => query.findUnique(),
364+
throwsA(predicate((UniqueViolationException e) =>
365+
e.toString().contains('more than one'))));
366+
367+
query.param(TestEntity_.tString).value = 't2';
368+
expect(query.findUnique()!.tString, 't2');
369+
370+
query.param(TestEntity_.tString).value = 'xyz';
371+
expect(query.findUnique(), isNull);
372+
});
373+
355374
test('.find works on large arrays', () {
356375
// This would fail on 32-bit system if objectbox-c obx_supports_bytes_array() wasn't respected
357376
final length = 10 * 1000;

0 commit comments

Comments
 (0)