Array of Primitives: RealmObjectSchema support#5329
Conversation
…notation_processor
…tive_list_9_RealmList
…notation_processor
…notation_processor
…notation_processor
…tive_list_9_RealmList
…notation_processor
…tive_list_9_RealmList
…tive_list_9_RealmList
- JavaAccessorContext. - Accessors for OsList. String and binary don't work yet. - Tests for OsList.
…tive_list_9_RealmList
…tive_list_9_RealmList
…tive_list_9_RealmList
| * @throws IllegalArgumentException if the field name is illegal, a field with that name already exists or | ||
| * the element type isn't supported. | ||
| * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable. | ||
| */ |
There was a problem hiding this comment.
I think naming elementType to be primitiveType would make this method easier to understand, that way you don't need to read the javadoc to know that this is for array of primitives only.
| FieldMetaData metadata = SUPPORTED_SIMPLE_FIELDS.get(primitiveType); | ||
| if (metadata == null) { | ||
| if (elementType.equals(RealmObjectSchema.class)) { | ||
| if (primitiveType.equals(RealmObjectSchema.class)) { |
There was a problem hiding this comment.
I wonder if this should check against if (primitiveType.equals(RealmObjectSchema.class) || RealmModel.class.isAssignableFrom(primitiveType)) { to ensure that they get this error message if they provide the Class<?> that belongs to a RealmModel.
Currently I think they'd get RealmList does not support lists with this type: "SomeRealmObject" which could be confusing.
There was a problem hiding this comment.
Yes, this would be nice. Fixing
| // All simple list types | ||
| schema.addRealmListField(fieldName, fieldType.getType()); | ||
| if (fieldType.isNullable()) { | ||
| schema.setRequired(fieldName, true); |
There was a problem hiding this comment.
are you changing the field from non-required to required?
There was a problem hiding this comment.
Yes, changing name of method to increase clarity
| } catch (IllegalArgumentException ignored) { | ||
| } | ||
| break; | ||
| default: |
There was a problem hiding this comment.
does this include all PRIMITIVE_* type as well? i.e setting primitive type to null? Shouldn't this throw?
arent' we missing if (!type.isNullable()) { continue; } ?
There was a problem hiding this comment.
I modified the enum, so it only contains non_list types. The lists are check in the next block
| break; | ||
| } | ||
| } | ||
| for (FieldListType fieldType : FieldListType.values()) { |
There was a problem hiding this comment.
there's no logic tested here? I wonder why you're keeping this block?
There was a problem hiding this comment.
A test was being added here in #5351 . I would prefer to keep this for now to decrease merge conflicts.
| return table->get_subdescriptor(col)->add_column(data_type, ObjectStore::ArrayColumnName, nullptr, is_column_nullable); | ||
| } | ||
| CATCH_STD() | ||
| return 0; |
There was a problem hiding this comment.
reinterpret_cast<jlong>(nullptr)
| * } | ||
| * </pre> | ||
| * If the list contains references to other Realm classes, then use | ||
| * If the list contains references to other Realm classes use |
There was a problem hiding this comment.
The comma was needed here 😛
| public <T> RealmList<T> getValueList(String fieldName, Class<T> valueClass) { | ||
| // TODO implement this | ||
| return null; | ||
| public <E> RealmList<E> getList(String fieldName, Class<E> elementType) { |
There was a problem hiding this comment.
Sooo, elementType vs primitiveType vs valueType?
There was a problem hiding this comment.
primitiveType.
I'm renaming variables right now 😛
| switch (columnType) { | ||
| case LIST: | ||
| //noinspection unchecked | ||
| setModelList(fieldName, (RealmList<DynamicRealmObject>) list); |
There was a problem hiding this comment.
I think there should be some kind of custom error message for providing a RealmList<? extends RealmModel> that is not RealmList<DynamicRealmObject>.
Currently it'll just throw a ClassCastException
| * @throws IllegalArgumentException if field name doesn't exist, it is not a list field, the type | ||
| * of the object represented by the DynamicRealmObject doesn't match or any element in the list belongs to a | ||
| * different Realm. | ||
| * @param list list of objects. Must either be primitive types or Realm objects. |
There was a problem hiding this comment.
This should be a bit more specific that it requires {@link DynamicRealmObject}.
…ass type. Add missing unit tests.
| schema.addRealmListField("field", AllJavaTypes.class); | ||
| fail(); | ||
| } catch (IllegalArgumentException e) { | ||
| assertTrue(e.getMessage().contains("Use 'addRealmListField(String name, RealmObjectSchema schema)' instead")); |
| FieldMetaData metadata = SUPPORTED_SIMPLE_FIELDS.get(primitiveType); | ||
| if (metadata == null) { | ||
| if (primitiveType.equals(RealmObjectSchema.class)) { | ||
| if (primitiveType.equals(RealmObjectSchema.class) || RealmModel.class.isAssignableFrom(primitiveType)) { |
| // to throw a better error message. | ||
| // Primitive types are checked inside `setModelList` | ||
| if (!list.isEmpty()) { | ||
| E element = list.first(); |
There was a problem hiding this comment.
I think just catching the possible ClassCastException and re-throwing it with the custom message would be more reliable and less hacky.
I like the message though!
There was a problem hiding this comment.
The classcast exception would not catch the generic parameter, only if RealmList was of the wrong type. Type erasure is a pain :(
There was a problem hiding this comment.
I see, I guess it'll do. Thank you! 🙂
This adds support for primitive lists to `RealmObjectSchema
Table.cpp#nativeConvertColumnToNotNullable andTable.cpp#nativeConvertColumnToNullable` so they work on both normal tables and sub tables. This is the biggest change, so please focus review there.Open questions:
Is
RealmObjectSchema.addRealmListField(String name, Class<?> class)the best name? We already haveRealmObjectSchema.addRealmListField(String name, RealmObjectSchema class), but is the overload weird? Another alternative could beaddPrimitiveRealmListField(name, class)oraddPrimitiveListField(name, class)? For the dynamic API, we havegetList(string fieldName). This will either need an overload withgetList(String fieldName, Class<?>orgetPrimitiveList(String fieldName, Class<?> clazz).Since these lists behavior is different from lists with Realm models, I would be tempted to go with:
or
ValueListis probably more technically correct as we also support more types than just the primitives, even though Date technically isn't a value type. On the other hand, I suspect thatprimitive typeis more familiar to people thanvalue type,So 3 proposals:
RealmObjectSchema.addRealmListField(String fieldName, Class<?> elementType);RealmObjectSchema.addRealmListField(String fieldName, RealmObjectSchema objectSchema);RealmList<E> list = DynamicRealmObject.getList(String fieldName, Class<?> elementType);RealmList<DynamicRealmObject> list = DynamicRealmObject.getList(String fieldName);primitive:RealmObjectSchema.addPrimitiveListField(String fieldName, Class<?> elementType);RealmObjectSchema.addRealmListField(String fieldName, RealmObjectSchema objectSchema);RealmList<E> list = DynamicRealmObject.getPrimitiveList(String fieldName, Class<E> elementType);RealmList<DynamicRealmObject> list = DynamicRealmObject.getList(String fieldName);value:RealmObjectSchema.addValueListField(String fieldName, Class<?> elementType);RealmObjectSchema.addRealmListField(String fieldName, RealmObjectSchema objectSchema);RealmList<E> list = DynamicRealmObject.getValueList(String fieldName, Class<E> elementType);RealmList<DynamicRealmObject> list = DynamicRealmObject.getList(String fieldName);Thoughts?
TODO
IndexFieldTypewith primitive list typesInvalidIndexFieldTypewith primitive list typesInvalidPrimaryKeyFieldTypewith primitive list types