Skip to content

putMany does not enforce @Unique ignores empty/null values #788

@1AlexFix1

Description

@1AlexFix1

I understand that I should check this myself using the unique identifier, but I'll describe it anyway just in case.

Description

When using putMany() with multiple entities that have the same value for a @Unique(onConflict: ConflictStrategy.replace) property, all entities are
inserted as separate rows instead of replacing each other. The ConflictStrategy.replace only resolves conflicts with entities that existed in the
database before the putMany() call, but does not check for conflicts between entities within the same batch.

This is unexpected — I would expect putMany([e1, e2, e3]) with the same unique value to result in only 1 entity (the last one), similar to calling
put(e1), put(e2), put(e3) sequentially.

Expected behavior

putMany with 10 entities sharing the same @Unique(onConflict: ConflictStrategy.replace) value should result in 1 entity in the database (the last
one replaces all previous).

Actual behavior

All 10 entities are inserted with different objId, completely ignoring the unique constraint within the batch.

Reproduction

@Entity()
class TestUniqueEntity {
  @Id()
  int objId = 0;

  @Unique(onConflict: ConflictStrategy.replace)
  String uid;

  String name;

  TestUniqueEntity({required this.uid, required this.name});
}

// Test code:
final box = store.box<TestUniqueEntity>();
box.removeAll();

final entities = List.generate(
  10,
  (i) => TestUniqueEntity(uid: '', name: 'field_$i'),
);

box.putMany(entities);

print('Count: ${box.count()}'); // Expected: 1, Actual: 10

final all = box.getAll();
for (final e in all) {
  print('objId=${e.objId}, uid="${e.uid}", name="${e.name}"');
}
// Prints 10 separate entities, all with uid=""

Output

Count: 10
objId=487, uid="", name="field_0"
objId=488, uid="", name="field_1"
objId=489, uid="", name="field_2"
objId=490, uid="", name="field_3"
objId=491, uid="", name="field_4"
objId=492, uid="", name="field_5"
objId=493, uid="", name="field_6"
objId=494, uid="", name="field_7"
objId=495, uid="", name="field_8"
objId=496, uid="", name="field_9"


Note

Sequential put() calls do enforce the constraint correctly — put(e2) replaces e1 if they share the same unique value. The issue is specific to putMany().

Version

- objectbox: 4.0.3
- Flutter 3.29.0

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions