diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 6b4c1b3d..8be4202f 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -33,7 +33,6 @@ 0270BC571B7CFC0D00010E03 /* RJSSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC491B7CFC0D00010E03 /* RJSSchema.mm */; }; 0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */; settings = {ATTRIBUTES = (Private, ); }; }; 0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */; }; - 0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */; }; 0270BC681B7CFC1C00010E03 /* object_accessor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */; }; 0270BC691B7CFC1C00010E03 /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */; }; 0270BC6A1B7CFC1C00010E03 /* object_schema.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */; }; @@ -158,7 +157,6 @@ 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSUtil.hpp; path = src/RJSUtil.hpp; sourceTree = ""; }; 0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RJSUtil.mm; path = src/RJSUtil.mm; sourceTree = ""; }; 0270BC5A1B7CFC1300010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = src/Info.plist; sourceTree = ""; }; - 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_accessor.cpp; path = "src/object-store/object_accessor.cpp"; sourceTree = ""; }; 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_accessor.hpp; path = "src/object-store/object_accessor.hpp"; sourceTree = ""; }; 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_schema.cpp; path = "src/object-store/object_schema.cpp"; sourceTree = ""; }; 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_schema.hpp; path = "src/object-store/object_schema.hpp"; sourceTree = ""; }; @@ -223,7 +221,6 @@ 0270BC3D1B7CFBFD00010E03 /* RealmJS */ = { isa = PBXGroup; children = ( - 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */, 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */, 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */, 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */, @@ -574,7 +571,6 @@ 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */, 0270BC6B1B7CFC1C00010E03 /* object_store.cpp in Sources */, 0270BC701B7CFC1C00010E03 /* shared_realm.cpp in Sources */, - 0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */, 0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */, 0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */, ); diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 94b5dec4..60e5a771 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -210,8 +210,8 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO return NULL; } -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list) { - return RJSWrapObject(ctx, RJSArrayClass(), list); +JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list) { + return RJSWrapObject(ctx, RJSArrayClass(), new List(list)); } const JSStaticFunction RJSArrayFuncs[] = { diff --git a/src/RJSArray.hpp b/src/RJSArray.hpp index 0cb70e36..3805646b 100644 --- a/src/RJSArray.hpp +++ b/src/RJSArray.hpp @@ -22,6 +22,6 @@ extern const JSStaticFunction RJSArrayFuncs[]; JSClassRef RJSArrayClass(); -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list); +JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list); JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 3333f73a..941e8504 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -29,49 +29,15 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) { - Object *obj = RJSGetInternal(jsObject); - - std::string propName = RJSStringForJSString(jsPropertyName); - ObjectSchema &objectSchema = obj->object_schema; - Property *prop = objectSchema.property_for_name(propName); - if (!prop) { + try { + Object *obj = RJSGetInternal(jsObject); + return obj->get_property_value(ctx, RJSStringForJSString(jsPropertyName)); + } catch (std::exception &ex) { + if (exception) { + *exception = RJSMakeError(ctx, ex); + } return NULL; } - - switch (prop->type) { - case PropertyTypeBool: - return JSValueMakeBoolean(ctx, obj->row.get_bool(prop->table_column)); - case PropertyTypeInt: - return JSValueMakeNumber(ctx, obj->row.get_int(prop->table_column)); - case PropertyTypeFloat: - return JSValueMakeNumber(ctx, obj->row.get_float(prop->table_column)); - case PropertyTypeDouble: - return JSValueMakeNumber(ctx, obj->row.get_double(prop->table_column)); - case PropertyTypeString: - return RJSValueForString(ctx, obj->row.get_string(prop->table_column)); - case PropertyTypeData: - return RJSValueForString(ctx, (std::string)obj->row.get_binary(prop->table_column)); - case PropertyTypeAny: - *exception = RJSMakeError(ctx, "'Any' type not supported"); - return NULL; - case PropertyTypeDate: { - JSValueRef time = JSValueMakeNumber(ctx, obj->row.get_datetime(prop->table_column).get_datetime()); - return JSObjectMakeDate(ctx, 1, &time, exception); - } - case PropertyTypeObject: { - auto linkObjectSchema = obj->realm->config().schema->find(prop->object_type); - TableRef table = ObjectStore::table_for_object_type(obj->realm->read_group(), linkObjectSchema->name); - if (obj->row.is_null_link(prop->table_column)) { - return JSValueMakeNull(ctx); - } - return RJSObjectCreate(ctx, Object(obj->realm, *linkObjectSchema, table->get(obj->row.get_link(prop->table_column)))); - } - case PropertyTypeArray: { - auto arrayObjectSchema = obj->realm->config().schema->find(prop->object_type); - return RJSArrayCreate(ctx, new List(obj->realm, *arrayObjectSchema, static_cast(obj->row.get_linklist(prop->table_column)))); - } - } - return NULL; } bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef value, JSValueRef* exception) { @@ -133,6 +99,9 @@ template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx, template<> bool RJSAccessor::is_null(JSContextRef ctx, JSValueRef &val) { return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val); } +template<> JSValueRef RJSAccessor::null_value(JSContextRef ctx) { + return JSValueMakeNull(ctx); +} template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) { if (!JSValueIsBoolean(ctx, val)) { @@ -140,22 +109,37 @@ template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) { } return JSValueToBoolean(ctx, val); } +template<> JSValueRef RJSAccessor::from_bool(JSContextRef ctx, bool b) { + return JSValueMakeBoolean(ctx, b); +} template<> long long RJSAccessor::to_long(JSContextRef ctx, JSValueRef &val) { return RJSValidatedValueToNumber(ctx, val); } +template<> JSValueRef RJSAccessor::from_long(JSContextRef ctx, long long l) { + return JSValueMakeNumber(ctx, l); +} template<> float RJSAccessor::to_float(JSContextRef ctx, JSValueRef &val) { return RJSValidatedValueToNumber(ctx, val); } +template<> JSValueRef RJSAccessor::from_float(JSContextRef ctx, float f) { + return JSValueMakeNumber(ctx, f); +} template<> double RJSAccessor::to_double(JSContextRef ctx, JSValueRef &val) { return RJSValidatedValueToNumber(ctx, val); } +template<> JSValueRef RJSAccessor::from_double(JSContextRef ctx, double d) { + return JSValueMakeNumber(ctx, d); +} template<> std::string RJSAccessor::to_string(JSContextRef ctx, JSValueRef &val) { return RJSValidatedStringForValue(ctx, val); } +template<> JSValueRef RJSAccessor::from_string(JSContextRef ctx, StringData s) { + return RJSValueForString(ctx, s); +} template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) { JSObjectRef object = RJSValidatedValueToObject(ctx, val, "Property must be a Date"); @@ -176,6 +160,10 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) return DateTime(utc); } +template<> JSValueRef RJSAccessor::from_datetime(JSContextRef ctx, DateTime dt) { + JSValueRef time = JSValueMakeNumber(ctx, dt.get_datetime()); + return JSObjectMakeDate(ctx, 1, &time, NULL); +} extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array); @@ -193,11 +181,16 @@ template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &re Object child = Object::create(ctx, realm, *object_schema, (JSValueRef)object, try_update); return child.row.get_index(); } - -template<> size_t RJSAccessor::array_size(JSContextRef ctx, JSValueRef &val) { - return RJSValidatedArrayLength(ctx, RJSValidatedValueToObject(ctx, val)); +template<> JSValueRef RJSAccessor::from_object(JSContextRef ctx, Object object) { + return RJSObjectCreate(ctx, object); } -template<> JSValueRef RJSAccessor::array_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) { +template<> size_t RJSAccessor::list_size(JSContextRef ctx, JSValueRef &val) { + return RJSValidatedListLength(ctx, RJSValidatedValueToObject(ctx, val)); +} +template<> JSValueRef RJSAccessor::list_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) { return RJSValidatedObjectAtIndex(ctx, RJSValidatedValueToObject(ctx, val), (unsigned int)index); } +template<> JSValueRef RJSAccessor::from_list(JSContextRef ctx, List list) { + return RJSArrayCreate(ctx, list); +} diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index aed02df9..9323ce99 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -221,7 +221,7 @@ JSValueRef RealmObjects(JSContextRef ctx, JSObjectRef function, JSObjectRef this JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array) { // copy to dictionary - if (object_schema.properties.size() != RJSValidatedArrayLength(ctx, array)) { + if (object_schema.properties.size() != RJSValidatedListLength(ctx, array)) { throw std::runtime_error("Array must contain values for all object properties"); } @@ -283,7 +283,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO JSValueIsObjectOfClass(ctx, arguments[0], RJSArrayClass())) { JSObjectRef array = RJSValidatedValueToObject(ctx, arguments[0]); - size_t length = RJSValidatedArrayLength(ctx, array); + size_t length = RJSValidatedListLength(ctx, array); for (long i = length-1; i >= 0; i--) { JSValueRef object = RJSValidatedObjectAtIndex(ctx, array, (unsigned int)i); RealmDelete(ctx, function, thisObject, 1, &object, jsException); diff --git a/src/RJSSchema.mm b/src/RJSSchema.mm index 534b44b5..ef9fdb12 100644 --- a/src/RJSSchema.mm +++ b/src/RJSSchema.mm @@ -127,7 +127,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob static JSStringRef nameString = JSStringCreateWithUTF8CString("name"); objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString); - size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject); + size_t numProperties = RJSValidatedListLength(ctx, propertiesObject); for (unsigned int p = 0; p < numProperties; p++) { JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p); objectSchema.properties.emplace_back(RJSParseProperty(ctx, property)); @@ -163,7 +163,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) { std::vector schema; - size_t length = RJSValidatedArrayLength(ctx, jsonObject); + size_t length = RJSValidatedListLength(ctx, jsonObject); for (unsigned int i = 0; i < length; i++) { JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i); ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema); diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 056b93bb..bb692d16 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -153,7 +153,7 @@ static inline std::string RJSValidatedStringProperty(JSContextRef ctx, JSObjectR return RJSValidatedStringForValue(ctx, propertyValue); } -static inline size_t RJSValidatedArrayLength(JSContextRef ctx, JSObjectRef object) { +static inline size_t RJSValidatedListLength(JSContextRef ctx, JSObjectRef object) { JSValueRef exception = NULL; static JSStringRef lengthString = JSStringCreateWithUTF8CString("length"); JSValueRef lengthValue = JSObjectGetProperty(ctx, object, lengthString, &exception); diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index 566c140e..d498d0c3 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -270,7 +270,7 @@ using RPCRequest = std::function; }; } else if (RJSIsValueArray(_context, value)) { - size_t length = RJSValidatedArrayLength(_context, jsObject); + size_t length = RJSValidatedListLength(_context, jsObject); NSMutableArray *array = [NSMutableArray new]; for (unsigned int i = 0; i < length; i++) { [array addObject:[self resultForJSValue:JSObjectGetPropertyAtIndex(_context, jsObject, i, NULL)]]; diff --git a/src/object-store/object_accessor.cpp b/src/object-store/object_accessor.cpp deleted file mode 100644 index 2516cc5d..00000000 --- a/src/object-store/object_accessor.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// - -#include "object_accessor.hpp" diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index fa6d6366..69bffa70 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -21,43 +21,9 @@ #include #include "shared_realm.hpp" +#include "list.hpp" namespace realm { - template - class NativeAccessor { - public: - // - // Value converters - template specializations must be implemented for each platform - // - static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); - static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); - - static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); - static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); - - static bool to_bool(ContextType ctx, ValueType &val); - static long long to_long(ContextType ctx, ValueType &val); - static float to_float(ContextType ctx, ValueType &val); - static double to_double(ContextType ctx, ValueType &val); - static std::string to_string(ContextType ctx, ValueType &val); - static DateTime to_datetime(ContextType ctx, ValueType &val); - - static bool is_null(ContextType ctx, ValueType &val); - - // convert value to persisted object - // for existing objects return the existing row index - // for new/updated objects return the row index - static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update); - - // array value acessors - static size_t array_size(ContextType ctx, ValueType &val); - static ValueType array_value_at_index(ContextType ctx, ValueType &val, size_t index); - - // - // Deprecated - // - static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); } - }; class Object { public: @@ -67,10 +33,13 @@ namespace realm { ObjectSchema &object_schema; Row row; - // property setter + // property getter/setter template inline void set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update); + template + inline ValueType get_property_value(ContextType ctx, std::string prop_name); + // create an Object from a native representation template static inline Object create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update); @@ -78,6 +47,53 @@ namespace realm { private: template inline void set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update); + template + inline ValueType get_property_value_impl(ContextType ctx, Property &property); + }; + + // + // Value converters - template specializations must be implemented for each platform in order to call templated methods on Object + // + template + class NativeAccessor { + public: + static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); + static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); + + static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); + static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); + + static bool to_bool(ContextType, ValueType &); + static ValueType from_bool(ContextType, bool); + static long long to_long(ContextType, ValueType &); + static ValueType from_long(ContextType, long long); + static float to_float(ContextType, ValueType &); + static ValueType from_float(ContextType, float); + static double to_double(ContextType, ValueType &); + static ValueType from_double(ContextType, double); + static std::string to_string(ContextType, ValueType &); + static ValueType from_string(ContextType, StringData); + static DateTime to_datetime(ContextType, ValueType &); + static ValueType from_datetime(ContextType, DateTime); + + static bool is_null(ContextType, ValueType &); + static ValueType null_value(ContextType); + + // convert value to persisted object + // for existing objects return the existing row index + // for new/updated objects return the row index + static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update); + static ValueType from_object(ContextType ctx, Object); + + // list value acessors + static size_t list_size(ContextType ctx, ValueType &val); + static ValueType list_value_at_index(ContextType ctx, ValueType &val, size_t index); + static ValueType from_list(ContextType ctx, List); + + // + // Deprecated + // + static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); } }; // @@ -93,6 +109,16 @@ namespace realm { set_property_value_impl(ctx, *prop, value, try_update); }; + template + inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name) + { + Property *prop = object_schema.property_for_name(prop_name); + if (!prop) { + throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + } + return get_property_value_impl(ctx, *prop); + }; + template inline void Object::set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update) { @@ -140,9 +166,9 @@ namespace realm { case PropertyTypeArray: { realm::LinkViewRef link_view = row.get_linklist(column); link_view->clear(); - size_t count = Accessor::array_size(ctx, value); + size_t count = Accessor::list_size(ctx, value); for (size_t i = 0; i < count; i++) { - ValueType element = Accessor::array_value_at_index(ctx, value, i); + ValueType element = Accessor::list_value_at_index(ctx, value, i); link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update)); } break; @@ -150,6 +176,44 @@ namespace realm { } } + template + inline ValueType Object::get_property_value_impl(ContextType ctx, Property &property) + { + using Accessor = NativeAccessor; + + size_t column = property.table_column; + switch (property.type) { + case PropertyTypeBool: + return Accessor::from_bool(ctx, row.get_bool(column)); + case PropertyTypeInt: + return Accessor::from_long(ctx, row.get_int(column)); + case PropertyTypeFloat: + return Accessor::from_float(ctx, row.get_float(column)); + case PropertyTypeDouble: + return Accessor::from_double(ctx, row.get_double(column)); + case PropertyTypeString: + return Accessor::from_string(ctx, row.get_string(column)); + case PropertyTypeData: + return Accessor::from_string(ctx, (std::string)row.get_binary(column)); + case PropertyTypeAny: + throw "Any not supported"; + case PropertyTypeDate: + return Accessor::from_datetime(ctx, row.get_datetime(column)); + case PropertyTypeObject: { + auto linkObjectSchema = realm->config().schema->find(property.object_type); + TableRef table = ObjectStore::table_for_object_type(realm->read_group(), linkObjectSchema->name); + if (row.is_null_link(property.table_column)) { + return Accessor::null_value(ctx); + } + return Accessor::from_object(ctx, std::move(Object(realm, *linkObjectSchema, table->get(row.get_link(column))))); + } + case PropertyTypeArray: { + auto arrayObjectSchema = realm->config().schema->find(property.object_type); + return Accessor::from_list(ctx, std::move(List(realm, *arrayObjectSchema, static_cast(row.get_linklist(column))))); + } + } + } + template inline Object Object::create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update) {