diff --git a/example/flutter/objectbox_demo/test_driver/app.dart b/example/flutter/objectbox_demo/test_driver/app.dart
index f4181aa4b..ace076df3 100644
--- a/example/flutter/objectbox_demo/test_driver/app.dart
+++ b/example/flutter/objectbox_demo/test_driver/app.dart
@@ -8,4 +8,4 @@ void main() {
// Call the `main()` function of the app, or call `runApp` with
// any widget you are interested in testing.
app.main();
-}
\ No newline at end of file
+}
diff --git a/generator/integration-tests/common.dart b/generator/integration-tests/common.dart
index 8509e1bab..99940d4c7 100644
--- a/generator/integration-tests/common.dart
+++ b/generator/integration-tests/common.dart
@@ -73,3 +73,10 @@ commonModelTests(ModelDefinition defs, ModelInfo jsonModel) {
ModelEntity entity(ModelInfo model, String name) {
return model.entities.firstWhere((ModelEntity e) => e.name == name);
}
+
+ModelProperty property(ModelInfo model, String path) {
+ final components = path.split('.');
+ return entity(model, components[0])
+ .properties
+ .firstWhere((ModelProperty p) => p.name == components[1]);
+}
diff --git a/generator/integration-tests/indexes/.gitignore b/generator/integration-tests/indexes/.gitignore
new file mode 100644
index 000000000..d5ba0726f
--- /dev/null
+++ b/generator/integration-tests/indexes/.gitignore
@@ -0,0 +1,2 @@
+# start with an empty project, without a objectbox-model.json
+objectbox-model.json
\ No newline at end of file
diff --git a/generator/integration-tests/indexes/1.dart b/generator/integration-tests/indexes/1.dart
new file mode 100644
index 000000000..fe84b5a31
--- /dev/null
+++ b/generator/integration-tests/indexes/1.dart
@@ -0,0 +1,47 @@
+import 'dart:io';
+import 'package:objectbox/objectbox.dart';
+
+import 'lib/lib.dart';
+import 'lib/objectbox.g.dart';
+import 'package:test/test.dart';
+import '../test_env.dart';
+import '../common.dart';
+import 'package:objectbox/src/bindings/bindings.dart';
+
+void main() {
+ TestEnv env;
+ final jsonModel = readModelJson('lib');
+ final defs = getObjectBoxModel();
+
+ setUp(() {
+ env = TestEnv(defs);
+ });
+
+ tearDown(() {
+ env.close();
+ });
+
+ commonModelTests(defs, jsonModel);
+
+ test('project must be generated properly', () {
+ expect(TestEnv.dir.existsSync(), true);
+ expect(File('lib/objectbox.g.dart').existsSync(), true);
+ expect(File('lib/objectbox-model.json').existsSync(), true);
+ });
+
+ test('property flags', () {
+ expect(property(jsonModel, 'A.id').flags, equals(OBXPropertyFlags.ID));
+ expect(property(jsonModel, 'A.indexed').flags,
+ equals(OBXPropertyFlags.INDEXED));
+ expect(property(jsonModel, 'A.unique').flags,
+ equals(OBXPropertyFlags.INDEX_HASH | OBXPropertyFlags.UNIQUE));
+ expect(property(jsonModel, 'A.uniqueValue').flags,
+ equals(OBXPropertyFlags.INDEXED | OBXPropertyFlags.UNIQUE));
+ expect(property(jsonModel, 'A.uniqueHash').flags,
+ equals(OBXPropertyFlags.INDEX_HASH | OBXPropertyFlags.UNIQUE));
+ expect(property(jsonModel, 'A.uniqueHash64').flags,
+ equals(OBXPropertyFlags.INDEX_HASH64 | OBXPropertyFlags.UNIQUE));
+ expect(property(jsonModel, 'A.uid').flags,
+ equals(OBXPropertyFlags.INDEXED | OBXPropertyFlags.UNIQUE));
+ });
+}
diff --git a/generator/integration-tests/indexes/lib/lib.dart b/generator/integration-tests/indexes/lib/lib.dart
new file mode 100644
index 000000000..1a78591ba
--- /dev/null
+++ b/generator/integration-tests/indexes/lib/lib.dart
@@ -0,0 +1,31 @@
+import 'package:objectbox/objectbox.dart';
+import 'objectbox.g.dart';
+
+@Entity()
+class A {
+ @Id()
+ int id;
+
+ @Index()
+ int indexed;
+
+ @Unique()
+ String unique;
+
+ @Unique()
+ @Index(type: IndexType.value)
+ String uniqueValue;
+
+ @Unique()
+ @Index(type: IndexType.hash)
+ String uniqueHash;
+
+ @Unique()
+ @Index(type: IndexType.hash64)
+ String uniqueHash64;
+
+ @Unique()
+ int uid;
+
+ A();
+}
diff --git a/generator/integration-tests/indexes/pubspec.yaml b/generator/integration-tests/indexes/pubspec.yaml
new file mode 120000
index 000000000..8d669e1bf
--- /dev/null
+++ b/generator/integration-tests/indexes/pubspec.yaml
@@ -0,0 +1 @@
+../shared-pubspec.yaml
\ No newline at end of file
diff --git a/generator/lib/src/code_builder.dart b/generator/lib/src/code_builder.dart
index 19b78ab78..3e0add71b 100644
--- a/generator/lib/src/code_builder.dart
+++ b/generator/lib/src/code_builder.dart
@@ -127,19 +127,24 @@ class CodeBuilder extends Builder {
'Entity ${entity.name}(${entity.id.toString()}) not found in the code, removing from the model');
model.removeEntity(entity);
});
-
- entities.forEach((entity) => mergeEntity(model, entity));
}
void mergeProperty(ModelEntity entity, ModelProperty prop) {
- final propInModel = entity.findSameProperty(prop);
+ var propInModel = entity.findSameProperty(prop);
+
if (propInModel == null) {
log.info('Found new property ${entity.name}.${prop.name}');
- entity.addProperty(prop);
+ propInModel = entity.createProperty(prop.name, prop.id.uid);
+ }
+
+ propInModel.name = prop.name;
+ propInModel.type = prop.type;
+ propInModel.flags = prop.flags;
+
+ if (!prop.hasIndexFlag()) {
+ propInModel.removeIndex();
} else {
- propInModel.name = prop.name;
- propInModel.type = prop.type;
- propInModel.flags = prop.flags;
+ propInModel.indexId ??= entity.model.createIndexId();
}
}
@@ -151,26 +156,26 @@ class CodeBuilder extends Builder {
if (entityInModel == null) {
log.info('Found new entity ${entity.name}');
// in case the entity is created (i.e. when its given UID or name that does not yet exist), we are done, as nothing needs to be merged
- entityInModel = modelInfo.addEntity(entity);
- } else {
- entityInModel.name = entity.name;
- entityInModel.flags = entity.flags;
-
- // here, the entity was found already and entityInModel and readEntity might differ, i.e. conflicts need to be resolved, so merge all properties first
- entity.properties.forEach((p) => mergeProperty(entityInModel, p));
-
- // then remove all properties not present anymore in readEntity
- final missingProps = entityInModel.properties
- .where((p) => entity.findSameProperty(p) == null)
- .toList(growable: false);
-
- missingProps.forEach((p) {
- log.warning(
- 'Property ${entity.name}.${p.name}(${p.id.toString()}) not found in the code, removing from the model');
- entityInModel.removeProperty(p);
- });
+ entityInModel = modelInfo.createEntity(entity.name, entity.id.uid);
}
+ entityInModel.name = entity.name;
+ entityInModel.flags = entity.flags;
+
+ // here, the entity was found already and entityInModel and readEntity might differ, i.e. conflicts need to be resolved, so merge all properties first
+ entity.properties.forEach((p) => mergeProperty(entityInModel, p));
+
+ // then remove all properties not present anymore in readEntity
+ final missingProps = entityInModel.properties
+ .where((p) => entity.findSameProperty(p) == null)
+ .toList(growable: false);
+
+ missingProps.forEach((p) {
+ log.warning(
+ 'Property ${entity.name}.${p.name}(${p.id.toString()}) not found in the code, removing from the model');
+ entityInModel.removeProperty(p);
+ });
+
return entityInModel.id;
}
}
diff --git a/generator/lib/src/entity_resolver.dart b/generator/lib/src/entity_resolver.dart
index 1de9a1935..5fa809595 100644
--- a/generator/lib/src/entity_resolver.dart
+++ b/generator/lib/src/entity_resolver.dart
@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
import 'package:build/build.dart';
import 'package:objectbox/objectbox.dart' as obx;
import 'package:objectbox/src/bindings/bindings.dart';
@@ -22,6 +23,8 @@ class EntityResolver extends Builder {
final _idChecker = const TypeChecker.fromRuntime(obx.Id);
final _transientChecker = const TypeChecker.fromRuntime(obx.Transient);
final _syncChecker = const TypeChecker.fromRuntime(obx.Sync);
+ final _uniqueChecker = const TypeChecker.fromRuntime(obx.Unique);
+ final _indexChecker = const TypeChecker.fromRuntime(obx.Index);
@override
FutureOr build(BuildStep buildStep) async {
@@ -140,13 +143,18 @@ class EntityResolver extends Builder {
}
// create property (do not use readEntity.createProperty in order to avoid generating new ids)
- final prop =
- ModelProperty(IdUid.empty(), f.name, fieldType, flags, entity);
+ final prop = ModelProperty(IdUid.empty(), f.name, fieldType,
+ flags: flags, entity: entity);
+
+ // Index and unique annotation.
+ final indexTypeStr =
+ processAnnotationIndexUnique(f, fieldType, elementBare, prop);
+
if (propUid != null) prop.id.uid = propUid;
entity.properties.add(prop);
log.info(
- ' property ${prop.name}(${prop.id}) type:${prop.type} flags:${prop.flags}');
+ ' property ${prop.name}(${prop.id}) type:${prop.type} flags:${prop.flags} ${prop.hasIndexFlag() ? "index:${indexTypeStr}" : ""}');
}
// some checks on the entity's integrity
@@ -157,4 +165,84 @@ class EntityResolver extends Builder {
return entity;
}
+
+ String processAnnotationIndexUnique(FieldElement f, int fieldType,
+ Element elementBare, obx.ModelProperty prop) {
+ obx.IndexType indexType;
+
+ final indexAnnotation = _indexChecker.firstAnnotationOfExact(f);
+ final hasUniqueAnnotation = _uniqueChecker.hasAnnotationOfExact(f);
+ if (indexAnnotation == null && !hasUniqueAnnotation) return null;
+
+ // Throw if property type does not support any index.
+ if (fieldType == OBXPropertyType.Float ||
+ fieldType == OBXPropertyType.Double ||
+ fieldType == OBXPropertyType.ByteVector) {
+ throw InvalidGenerationSourceError(
+ "in target ${elementBare.name}: @Index/@Unique is not supported for type '${f.type.toString()}' of field '${f.name}'");
+ }
+
+ if (prop.hasFlag(OBXPropertyFlags.ID)) {
+ throw InvalidGenerationSourceError(
+ 'in target ${elementBare.name}: @Index/@Unique is not supported for ID field ${f.name}. IDs are unique by definition and automatically indexed');
+ }
+
+ // If available use index type from annotation.
+ if (indexAnnotation != null && !indexAnnotation.isNull) {
+ // find out @Index(type:) value - its an enum IndexType
+ final indexTypeField = indexAnnotation.getField('type');
+ if (!indexTypeField.isNull) {
+ final indexTypeEnumValues = (indexTypeField.type as InterfaceType)
+ .element
+ .fields
+ .where((f) => f.isEnumConstant)
+ .toList();
+
+ // Find the index of the matching enum constant.
+ for (var i = 0; i < indexTypeEnumValues.length; i++) {
+ if (indexTypeEnumValues[i].computeConstantValue() == indexTypeField) {
+ indexType = obx.IndexType.values[i];
+ break;
+ }
+ }
+ }
+ }
+
+ // Fall back to index type based on property type.
+ final supportsHashIndex = fieldType == OBXPropertyType.String;
+ if (indexType == null) {
+ if (supportsHashIndex) {
+ indexType = obx.IndexType.hash;
+ } else {
+ indexType = obx.IndexType.value;
+ }
+ }
+
+ // Throw if HASH or HASH64 is not supported by property type.
+ if (!supportsHashIndex &&
+ (indexType == obx.IndexType.hash ||
+ indexType == obx.IndexType.hash64)) {
+ throw InvalidGenerationSourceError(
+ "in target ${elementBare.name}: a hash index is not supported for type '${f.type.toString()}' of field '${f.name}'");
+ }
+
+ if (hasUniqueAnnotation) {
+ prop.flags |= OBXPropertyFlags.UNIQUE;
+ }
+
+ switch (indexType) {
+ case obx.IndexType.value:
+ prop.flags |= OBXPropertyFlags.INDEXED;
+ return 'value';
+ case obx.IndexType.hash:
+ prop.flags |= OBXPropertyFlags.INDEX_HASH;
+ return 'hash';
+ case obx.IndexType.hash64:
+ prop.flags |= OBXPropertyFlags.INDEX_HASH64;
+ return 'hash64';
+ default:
+ throw InvalidGenerationSourceError(
+ 'in target ${elementBare.name}: invalid index type: $indexType');
+ }
+ }
}
diff --git a/generator/test.sh b/generator/test.sh
index 2be995c13..0e6a002a1 100755
--- a/generator/test.sh
+++ b/generator/test.sh
@@ -15,7 +15,7 @@ function runTestFile() {
# build before each step, except for "0.dart"
if [ "${1}" != "0" ]; then
echo "Running build_runner before ${file}"
- dart pub run build_runner build
+ dart pub run build_runner build --verbose
fi
echo "Running ${file}"
dart test "${file}"
diff --git a/lib/integration_test.dart b/lib/integration_test.dart
index 2c435ac75..af38d0287 100644
--- a/lib/integration_test.dart
+++ b/lib/integration_test.dart
@@ -18,8 +18,8 @@ class IntegrationTest {
static void model() {
// create a model with a single entity and a single property
final modelInfo = ModelInfo();
- final property = ModelProperty(
- IdUid(1, int64_max - 1), 'id', OBXPropertyType.Long, 0, null);
+ final property =
+ ModelProperty(IdUid(1, int64_max - 1), 'id', OBXPropertyType.Long);
final entity = ModelEntity(IdUid(1, int64_max), 'entity', modelInfo);
property.entity = entity;
entity.properties.add(property);
diff --git a/lib/src/annotations.dart b/lib/src/annotations.dart
index 76aa4799c..92c716a24 100644
--- a/lib/src/annotations.dart
+++ b/lib/src/annotations.dart
@@ -33,3 +33,34 @@ class Transient {
// class Sync {
// const Sync();
// }
+
+/// Specifies that the property should be indexed.
+///
+/// It is highly recommended to index properties that are used in a Query to
+/// improve query performance. To fine tune indexing of a property you can
+/// override the default index type.
+///
+/// Note: indexes are currently not supported for ByteVector, Float or Double
+/// properties.
+class Index {
+ final IndexType /*?*/ type;
+ const Index({this.type});
+}
+
+enum IndexType {
+ value,
+ hash,
+ hash64,
+}
+
+/// Enforces that the value of a property is unique among all Objects in a Box
+/// before an Object can be put.
+///
+/// Trying to put an Object with offending values will result in an exception.
+///
+/// Unique properties are based on an [Index], so the same restrictions apply.
+/// It is supported to explicitly add the [Index] annotation to configure the
+/// index type.
+class Unique {
+ const Unique();
+}
diff --git a/lib/src/model.dart b/lib/src/model.dart
index 48f546152..3fae9e97b 100644
--- a/lib/src/model.dart
+++ b/lib/src/model.dart
@@ -19,6 +19,12 @@ class Model {
// set last entity id
bindings.obx_model_last_entity_id(
_cModel, model.lastEntityId.id, model.lastEntityId.uid);
+
+ // set last index id
+ if (model.lastIndexId != null) {
+ bindings.obx_model_last_index_id(
+ _cModel, model.lastIndexId.id, model.lastIndexId.uid);
+ }
} catch (e) {
bindings.obx_model_free(_cModel);
rethrow;
@@ -67,6 +73,11 @@ class Model {
try {
_check(bindings.obx_model_property(
_cModel, name, prop.type, prop.id.id, prop.id.uid));
+
+ if (prop.indexId != null) {
+ _check(bindings.obx_model_property_index_id(
+ _cModel, prop.indexId.id, prop.indexId.uid));
+ }
} finally {
free(name);
}
diff --git a/lib/src/modelinfo/modelentity.dart b/lib/src/modelinfo/modelentity.dart
index 19c9f2507..d98b6040a 100644
--- a/lib/src/modelinfo/modelentity.dart
+++ b/lib/src/modelinfo/modelentity.dart
@@ -142,17 +142,11 @@ class ModelEntity {
}
final uniqueUid = uid == 0 ? model.generateUid() : uid;
- var property = ModelProperty(IdUid(id, uniqueUid), name, 0, 0, this);
+ final property = ModelProperty(IdUid(id, uniqueUid), name, 0, entity: this);
properties.add(property);
lastPropertyId = property.id;
- return property;
- }
- ModelProperty addProperty(ModelProperty prop) {
- final modelProp = createProperty(prop.name, prop.id.uid);
- modelProp.type = prop.type;
- modelProp.flags = prop.flags;
- return modelProp;
+ return property;
}
void removeProperty(ModelProperty prop) {
@@ -163,6 +157,10 @@ class ModelEntity {
}
_properties.remove(foundProp);
model.retiredPropertyUids.add(prop.id.uid);
+
+ if (prop.indexId != null) {
+ model.retiredIndexUids.add(prop.indexId.uid);
+ }
}
bool containsUid(int searched) {
diff --git a/lib/src/modelinfo/modelinfo.dart b/lib/src/modelinfo/modelinfo.dart
index 657c596e0..d198d859d 100644
--- a/lib/src/modelinfo/modelinfo.dart
+++ b/lib/src/modelinfo/modelinfo.dart
@@ -152,12 +152,6 @@ class ModelInfo {
return ret;
}
- ModelEntity addEntity(ModelEntity other) {
- final modelEntity = createEntity(other.name, other.id.uid);
- other.properties.forEach((p) => modelEntity.addProperty(p));
- return modelEntity;
- }
-
ModelEntity createEntity(String name, [int uid = 0]) {
var id = 1;
if (entities.isNotEmpty) id = lastEntityId.id + 1;
@@ -208,4 +202,10 @@ class ModelInfo {
if (listContains(retiredRelationUids, uid)) return true;
return false;
}
+
+ IdUid createIndexId() {
+ var id = lastIndexId.isEmpty ? 1 : lastIndexId.id + 1;
+ lastIndexId = IdUid(id, generateUid());
+ return lastIndexId;
+ }
}
diff --git a/lib/src/modelinfo/modelproperty.dart b/lib/src/modelinfo/modelproperty.dart
index b73c9b319..32cf5312c 100644
--- a/lib/src/modelinfo/modelproperty.dart
+++ b/lib/src/modelinfo/modelproperty.dart
@@ -1,3 +1,5 @@
+import 'package:objectbox/src/bindings/bindings.dart';
+
import 'modelentity.dart';
import 'iduid.dart';
@@ -6,6 +8,7 @@ class ModelProperty {
IdUid id;
/*late*/ String _name;
/*late*/ int _type, _flags;
+ IdUid /*?*/ _indexId;
ModelEntity /*?*/ entity;
String get name => _name;
@@ -35,16 +38,30 @@ class ModelProperty {
_flags = value /*!*/;
}
- ModelProperty(this.id, String /*?*/ name, int /*?*/ type, int /*?*/ flags,
- this.entity) {
+ IdUid /*?*/ get indexId => _indexId;
+
+ set indexId(IdUid /*?*/ value) {
+ if (value != null) {
+ if (value.id == 0 || value.uid == 0) {
+ throw Exception('indexId must contain valid ID & UID');
+ }
+ }
+ _indexId = value /*!*/;
+ }
+
+ ModelProperty(this.id, String /*?*/ name, int /*?*/ type,
+ {int flags = 0, String /*?*/ indexId, this.entity}) {
this.name = name;
this.type = type;
this.flags = flags;
+ this.indexId = indexId == null ? null : IdUid.fromString(indexId);
}
ModelProperty.fromMap(Map data, ModelEntity /*?*/ entity)
: this(IdUid.fromString(data['id']), data['name'], data['type'],
- data['flags'] ?? 0, entity);
+ flags: data['flags'] ?? 0,
+ indexId: data['indexId'],
+ entity: entity);
Map toMap() {
final ret = {};
@@ -52,6 +69,7 @@ class ModelProperty {
ret['name'] = name;
ret['type'] = type;
if (flags != 0) ret['flags'] = flags;
+ if (indexId != null) ret['indexId'] = indexId /*!*/ .toString();
return ret;
}
@@ -62,4 +80,17 @@ class ModelProperty {
bool hasFlag(int flag) {
return (flags & flag) == flag;
}
+
+ bool hasIndexFlag() {
+ return hasFlag(OBXPropertyFlags.INDEXED) ||
+ hasFlag(OBXPropertyFlags.INDEX_HASH) ||
+ hasFlag(OBXPropertyFlags.INDEX_HASH64);
+ }
+
+ void removeIndex() {
+ if (_indexId != null) {
+ entity.model.retiredIndexUids.add(_indexId.uid);
+ indexId = null;
+ }
+ }
}
diff --git a/test/box_test.dart b/test/box_test.dart
index ac877cfff..c3f10bdf5 100644
--- a/test/box_test.dart
+++ b/test/box_test.dart
@@ -58,6 +58,18 @@ void main() {
expect(item.tString, equals('Two'));
});
+ test('.put() cannot add duplicate values on a unique field', () {
+ final u1 = TestEntity.unique(
+ uString: 'a', uLong: 1, uInt: 1, uShort: 1, uByte: 1, uChar: 1);
+ final again = TestEntity.unique(
+ uString: 'a', uLong: 1, uInt: 1, uShort: 1, uByte: 1, uChar: 1);
+
+ expect(
+ () => box.putMany([u1, again]),
+ throwsA(predicate((ObjectBoxException e) =>
+ e.toString().contains('same property value already exists'))));
+ });
+
test('.getAll retrieves all items', () {
final int id1 = box.put(TestEntity(tString: 'One'));
final int id2 = box.put(TestEntity(tString: 'Two'));
diff --git a/test/entity.dart b/test/entity.dart
index b3ce00fda..2086191b4 100644
--- a/test/entity.dart
+++ b/test/entity.dart
@@ -1,4 +1,5 @@
import 'package:objectbox/objectbox.dart';
+import 'package:objectbox/src/bindings/bindings.dart';
/// A dummy annotation to verify the code is generated properly even with annotations unknown to ObjectBox generator.
class TestingUnknownAnnotation {
@@ -28,23 +29,23 @@ class TestEntity {
// explicitly declared types, see OB-C, objectbox.h
// OBXPropertyType.Byte | 1 byte
- @Property(type: 2)
+ @Property(type: OBXPropertyType.Byte)
int /*?*/ tByte;
// OBXPropertyType.Short | 2 bytes
- @Property(type: 3)
+ @Property(type: OBXPropertyType.Short)
int /*?*/ tShort;
// OBXPropertyType.Char | 1 byte
- @Property(type: 4)
+ @Property(type: OBXPropertyType.Char)
int /*?*/ tChar;
// OBXPropertyType.Int | ob: 4 bytes, dart: 8 bytes
- @Property(type: 5)
+ @Property(type: OBXPropertyType.Int)
int /*?*/ tInt;
// OBXPropertyType.Float | 4 bytes
- @Property(type: 7)
+ @Property(type: OBXPropertyType.Float)
double /*?*/ tFloat;
TestEntity(
@@ -64,4 +65,68 @@ class TestEntity {
omit = -1;
disregard = 1;
}
+
+ @Property(type: OBXPropertyType.Byte)
+ @Unique()
+ int uByte;
+
+ @Property(type: OBXPropertyType.Short)
+ @Unique()
+ int uShort;
+
+ @Property(type: OBXPropertyType.Char)
+ @Unique()
+ int uChar;
+
+ @Property(type: OBXPropertyType.Int)
+ @Unique()
+ int uInt;
+
+ // implicitly determined types
+ @Unique()
+ String uString;
+
+ @Unique()
+ int uLong;
+
+ TestEntity.unique({
+ this.uString,
+ this.uLong,
+ this.uInt,
+ this.uShort,
+ this.uByte,
+ this.uChar,
+ });
+
+ @Property(type: OBXPropertyType.Byte)
+ @Index()
+ int iByte;
+
+ @Property(type: OBXPropertyType.Short)
+ @Index()
+ int iShort;
+
+ @Property(type: OBXPropertyType.Char)
+ @Index()
+ int iChar;
+
+ @Property(type: OBXPropertyType.Int)
+ @Index()
+ int iInt;
+
+ // implicitly determined types
+ @Index()
+ String iString;
+
+ @Index()
+ int iLong;
+
+ TestEntity.index({
+ this.iString,
+ this.iLong,
+ this.iInt,
+ this.iShort,
+ this.iByte,
+ this.iChar,
+ });
}
diff --git a/test/objectbox-model.json b/test/objectbox-model.json
index c081e636a..2ad506fce 100644
--- a/test/objectbox-model.json
+++ b/test/objectbox-model.json
@@ -5,7 +5,7 @@
"entities": [
{
"id": "1:4630700155272683157",
- "lastPropertyId": "14:2723176855509462268",
+ "lastPropertyId": "26:3059114515142777989",
"name": "TestEntity",
"flags": 2,
"properties": [
@@ -59,6 +59,90 @@
"id": "14:2723176855509462268",
"name": "tFloat",
"type": 7
+ },
+ {
+ "id": "15:5960097736918862689",
+ "name": "uByte",
+ "type": 2,
+ "flags": 40,
+ "indexId": "1:759265819613755228"
+ },
+ {
+ "id": "16:3014870337091941693",
+ "name": "uShort",
+ "type": 3,
+ "flags": 40,
+ "indexId": "2:3731424852781354288"
+ },
+ {
+ "id": "17:3004362051550241897",
+ "name": "uChar",
+ "type": 4,
+ "flags": 40,
+ "indexId": "3:1180301620695216647"
+ },
+ {
+ "id": "18:1083874867412561588",
+ "name": "uInt",
+ "type": 5,
+ "flags": 40,
+ "indexId": "4:9159391309201422019"
+ },
+ {
+ "id": "19:1849261948480372113",
+ "name": "uString",
+ "type": 9,
+ "flags": 2080,
+ "indexId": "5:7090314366957370493"
+ },
+ {
+ "id": "20:1700905145011245158",
+ "name": "uLong",
+ "type": 6,
+ "flags": 40,
+ "indexId": "6:9146355272521890356"
+ },
+ {
+ "id": "21:1256214340403371310",
+ "name": "iByte",
+ "type": 2,
+ "flags": 8,
+ "indexId": "7:2597915862881161952"
+ },
+ {
+ "id": "22:5768208836201983752",
+ "name": "iShort",
+ "type": 3,
+ "flags": 8,
+ "indexId": "8:5900854653402683567"
+ },
+ {
+ "id": "23:2550226115516189529",
+ "name": "iChar",
+ "type": 4,
+ "flags": 8,
+ "indexId": "9:6832522351412488843"
+ },
+ {
+ "id": "24:8654682464442924778",
+ "name": "iInt",
+ "type": 5,
+ "flags": 8,
+ "indexId": "10:7301436684067319059"
+ },
+ {
+ "id": "25:6667369331692110338",
+ "name": "iString",
+ "type": 9,
+ "flags": 2048,
+ "indexId": "11:4395163045094957195"
+ },
+ {
+ "id": "26:3059114515142777989",
+ "name": "iLong",
+ "type": 6,
+ "flags": 8,
+ "indexId": "12:5335419474465474748"
}
]
},
@@ -77,7 +161,7 @@
}
],
"lastEntityId": "3:3569200127393812728",
- "lastIndexId": "0:0",
+ "lastIndexId": "12:5335419474465474748",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 5,
diff --git a/test/query_test.dart b/test/query_test.dart
index 843029999..e4c92bead 100644
--- a/test/query_test.dart
+++ b/test/query_test.dart
@@ -295,7 +295,7 @@ void main() {
final remaining = box.getAll();
expect(remaining.length, 2);
- expect(remaining.map((e) => e.id), equals([1,4]));
+ expect(remaining.map((e) => e.id), equals([1, 4]));
});
test('.count items after grouping with and/or', () {