mirror of
https://github.com/status-im/realm-js.git
synced 2025-02-02 09:46:28 +00:00
parent
cb889ea8f8
commit
cd0bb079b7
@ -106,6 +106,15 @@ export default class Realm {
|
|||||||
let method = util.createMethod(objectTypes.REALM, 'objects');
|
let method = util.createMethod(objectTypes.REALM, 'objects');
|
||||||
return method.apply(this, [type, ...args]);
|
return method.apply(this, [type, ...args]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
objectForPrimaryKey(type, ...args) {
|
||||||
|
if (typeof type == 'function') {
|
||||||
|
type = objects.typeForConstructor(this[keys.realm], type);
|
||||||
|
}
|
||||||
|
|
||||||
|
let method = util.createMethod(objectTypes.REALM, 'objectForPrimaryKey');
|
||||||
|
return method.apply(this, [type, ...args]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-mutating methods:
|
// Non-mutating methods:
|
||||||
|
@ -141,6 +141,7 @@ public:
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
static void objects(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
static void objects(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void object_for_primary_key(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
static void create(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
static void create(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
static void delete_one(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
static void delete_one(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
static void delete_all(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
static void delete_all(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
@ -180,6 +181,7 @@ public:
|
|||||||
|
|
||||||
MethodMap<T> const methods = {
|
MethodMap<T> const methods = {
|
||||||
{"objects", wrap<objects>},
|
{"objects", wrap<objects>},
|
||||||
|
{"objectForPrimaryKey", wrap<object_for_primary_key>},
|
||||||
{"create", wrap<create>},
|
{"create", wrap<create>},
|
||||||
{"delete", wrap<delete_one>},
|
{"delete", wrap<delete_one>},
|
||||||
{"deleteAll", wrap<delete_all>},
|
{"deleteAll", wrap<delete_all>},
|
||||||
@ -207,19 +209,35 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// converts constructor object or type name to type name
|
// converts constructor object or type name to type name
|
||||||
static std::string validated_object_type_for_value(SharedRealm &realm, ContextType ctx, const ValueType &value) {
|
static const ObjectSchema& validated_object_schema_for_value(ContextType ctx, const SharedRealm &realm, const ValueType &value) {
|
||||||
|
std::string object_type;
|
||||||
|
|
||||||
if (Value::is_constructor(ctx, value)) {
|
if (Value::is_constructor(ctx, value)) {
|
||||||
FunctionType constructor = Value::to_constructor(ctx, value);
|
FunctionType constructor = Value::to_constructor(ctx, value);
|
||||||
|
|
||||||
auto delegate = get_delegate<T>(realm.get());
|
auto delegate = get_delegate<T>(realm.get());
|
||||||
for (auto &pair : delegate->m_constructors) {
|
for (auto &pair : delegate->m_constructors) {
|
||||||
if (FunctionType(pair.second) == constructor) {
|
if (FunctionType(pair.second) == constructor) {
|
||||||
return pair.first;
|
object_type = pair.first;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object_type.empty()) {
|
||||||
throw std::runtime_error("Constructor was not registered in the schema for this Realm");
|
throw std::runtime_error("Constructor was not registered in the schema for this Realm");
|
||||||
}
|
}
|
||||||
return Value::validated_to_string(ctx, value, "objectType");
|
}
|
||||||
|
else {
|
||||||
|
object_type = Value::validated_to_string(ctx, value, "objectType");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &schema = realm->config().schema;
|
||||||
|
auto object_schema = schema->find(object_type);
|
||||||
|
|
||||||
|
if (object_schema == schema->end()) {
|
||||||
|
throw std::runtime_error("Object type '" + object_type + "' not found in schema.");
|
||||||
|
}
|
||||||
|
return *object_schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string normalize_path(std::string path) {
|
static std::string normalize_path(std::string path) {
|
||||||
@ -462,9 +480,25 @@ void RealmClass<T>::objects(ContextType ctx, ObjectType this_object, size_t argc
|
|||||||
validate_argument_count(argc, 1);
|
validate_argument_count(argc, 1);
|
||||||
|
|
||||||
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
|
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
|
||||||
std::string type = validated_object_type_for_value(realm, ctx, arguments[0]);
|
auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0]);
|
||||||
|
|
||||||
return_value.set(ResultsClass<T>::create_instance(ctx, realm, type));
|
return_value.set(ResultsClass<T>::create_instance(ctx, realm, object_schema));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void RealmClass<T>::object_for_primary_key(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
validate_argument_count(argc, 2);
|
||||||
|
|
||||||
|
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
|
||||||
|
auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0]);
|
||||||
|
auto realm_object = realm::Object::get_for_primary_key(ctx, realm, object_schema, arguments[1]);
|
||||||
|
|
||||||
|
if (realm_object.is_valid()) {
|
||||||
|
return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return_value.set_undefined();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -472,17 +506,11 @@ void RealmClass<T>::create(ContextType ctx, ObjectType this_object, size_t argc,
|
|||||||
validate_argument_count(argc, 2, 3);
|
validate_argument_count(argc, 2, 3);
|
||||||
|
|
||||||
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
|
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
|
||||||
std::string className = validated_object_type_for_value(realm, ctx, arguments[0]);
|
auto &object_schema = validated_object_schema_for_value(ctx, realm, arguments[0]);
|
||||||
auto &schema = realm->config().schema;
|
|
||||||
auto object_schema = schema->find(className);
|
|
||||||
|
|
||||||
if (object_schema == schema->end()) {
|
|
||||||
throw std::runtime_error("Object type '" + className + "' not found in schema.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectType object = Value::validated_to_object(ctx, arguments[1], "properties");
|
ObjectType object = Value::validated_to_object(ctx, arguments[1], "properties");
|
||||||
if (Value::is_array(ctx, arguments[1])) {
|
if (Value::is_array(ctx, arguments[1])) {
|
||||||
object = Schema<T>::dict_for_property_array(ctx, *object_schema, object);
|
object = Schema<T>::dict_for_property_array(ctx, object_schema, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update = false;
|
bool update = false;
|
||||||
@ -490,7 +518,7 @@ void RealmClass<T>::create(ContextType ctx, ObjectType this_object, size_t argc,
|
|||||||
update = Value::validated_to_boolean(ctx, arguments[2], "update");
|
update = Value::validated_to_boolean(ctx, arguments[2], "update");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto realm_object = realm::Object::create<ValueType>(ctx, realm, *object_schema, object, update);
|
auto realm_object = realm::Object::create<ValueType>(ctx, realm, object_schema, object, update);
|
||||||
return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
|
return_value.set(RealmObjectClass<T>::create_instance(ctx, std::move(realm_object)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ struct ResultsClass : ClassDefinition<T, realm::Results, CollectionClass<T>> {
|
|||||||
|
|
||||||
static ObjectType create_instance(ContextType, const realm::Results &, bool live = true);
|
static ObjectType create_instance(ContextType, const realm::Results &, bool live = true);
|
||||||
static ObjectType create_instance(ContextType, const realm::List &, bool live = true);
|
static ObjectType create_instance(ContextType, const realm::List &, bool live = true);
|
||||||
static ObjectType create_instance(ContextType, SharedRealm, const std::string &type, bool live = true);
|
static ObjectType create_instance(ContextType, SharedRealm, const ObjectSchema &, bool live = true);
|
||||||
static ObjectType create_instance(ContextType, SharedRealm, const ObjectSchema &, Query, bool live = true);
|
static ObjectType create_instance(ContextType, SharedRealm, const ObjectSchema &, Query, bool live = true);
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
@ -87,16 +87,9 @@ typename T::Object ResultsClass<T>::create_instance(ContextType ctx, const realm
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename T::Object ResultsClass<T>::create_instance(ContextType ctx, SharedRealm realm, const std::string &type, bool live) {
|
typename T::Object ResultsClass<T>::create_instance(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, bool live) {
|
||||||
auto table = ObjectStore::table_for_object_type(realm->read_group(), type);
|
auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
|
||||||
auto &schema = realm->config().schema;
|
auto results = new realm::Results(realm, object_schema, *table);
|
||||||
auto object_schema = schema->find(type);
|
|
||||||
|
|
||||||
if (object_schema == schema->end()) {
|
|
||||||
throw std::runtime_error("Object type '" + type + "' not present in Realm.");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto results = new realm::Results(realm, *object_schema, *table);
|
|
||||||
results->set_live(live);
|
results->set_live(live);
|
||||||
|
|
||||||
return create_object<T, ResultsClass<T>>(ctx, results);
|
return create_object<T, ResultsClass<T>>(ctx, results);
|
||||||
|
@ -45,6 +45,9 @@ namespace realm {
|
|||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update);
|
static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update);
|
||||||
|
|
||||||
|
template<typename ValueType, typename ContextType>
|
||||||
|
static Object get_for_primary_key(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType primary_value);
|
||||||
|
|
||||||
SharedRealm realm() { return m_realm; }
|
SharedRealm realm() { return m_realm; }
|
||||||
const ObjectSchema &get_object_schema() { return *m_object_schema; }
|
const ObjectSchema &get_object_schema() { return *m_object_schema; }
|
||||||
Row row() { return m_row; }
|
Row row() { return m_row; }
|
||||||
@ -61,6 +64,9 @@ namespace realm {
|
|||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
inline ValueType get_property_value_impl(ContextType ctx, const Property &property);
|
inline ValueType get_property_value_impl(ContextType ctx, const Property &property);
|
||||||
|
|
||||||
|
template<typename ValueType, typename ContextType>
|
||||||
|
static size_t get_for_primary_key_impl(ContextType ctx, const ConstTableRef &table, const Property &primary_prop, ValueType primary_value);
|
||||||
|
|
||||||
inline void verify_attached();
|
inline void verify_attached();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -137,6 +143,13 @@ namespace realm {
|
|||||||
const std::string property_name;
|
const std::string property_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MissingPrimaryKeyException : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MissingPrimaryKeyException(const std::string object_type, const std::string message) : std::runtime_error(message), object_type(object_type) {}
|
||||||
|
const std::string object_type;
|
||||||
|
};
|
||||||
|
|
||||||
class MutationOutsideTransactionException : public std::runtime_error
|
class MutationOutsideTransactionException : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -301,16 +314,11 @@ namespace realm {
|
|||||||
size_t row_index = realm::not_found;
|
size_t row_index = realm::not_found;
|
||||||
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
|
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
|
||||||
const Property *primary_prop = object_schema.primary_key_property();
|
const Property *primary_prop = object_schema.primary_key_property();
|
||||||
|
|
||||||
if (primary_prop) {
|
if (primary_prop) {
|
||||||
// search for existing object based on primary key type
|
// search for existing object based on primary key type
|
||||||
ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key);
|
ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key);
|
||||||
if (primary_prop->type == PropertyType::String) {
|
row_index = get_for_primary_key_impl(ctx, table, *primary_prop, primary_value);
|
||||||
auto primary_string = Accessor::to_string(ctx, primary_value);
|
|
||||||
row_index = table->find_first_string(primary_prop->table_column, primary_string);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
row_index = table->find_first_int(primary_prop->table_column, Accessor::to_long(ctx, primary_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!try_update && row_index != realm::not_found) {
|
if (!try_update && row_index != realm::not_found) {
|
||||||
throw DuplicatePrimaryKeyValueException(object_schema.name, *primary_prop,
|
throw DuplicatePrimaryKeyValueException(object_schema.name, *primary_prop,
|
||||||
@ -349,6 +357,33 @@ namespace realm {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ValueType, typename ContextType>
|
||||||
|
inline Object Object::get_for_primary_key(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType primary_value)
|
||||||
|
{
|
||||||
|
auto primary_prop = object_schema.primary_key_property();
|
||||||
|
if (!primary_prop) {
|
||||||
|
throw MissingPrimaryKeyException(object_schema.name, object_schema.name + " does not have a primary key");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
|
||||||
|
auto row_index = get_for_primary_key_impl(ctx, table, *primary_prop, primary_value);
|
||||||
|
|
||||||
|
return Object(realm, object_schema, row_index == realm::not_found ? Row() : table->get(row_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType, typename ContextType>
|
||||||
|
inline size_t Object::get_for_primary_key_impl(ContextType ctx, const ConstTableRef &table, const Property &primary_prop, ValueType primary_value) {
|
||||||
|
using Accessor = NativeAccessor<ValueType, ContextType>;
|
||||||
|
|
||||||
|
if (primary_prop.type == PropertyType::String) {
|
||||||
|
auto primary_string = Accessor::to_string(ctx, primary_value);
|
||||||
|
return table->find_first_string(primary_prop.table_column, primary_string);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return table->find_first_int(primary_prop.table_column, Accessor::to_long(ctx, primary_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void Object::verify_attached() {
|
inline void Object::verify_attached() {
|
||||||
if (!m_row.is_attached()) {
|
if (!m_row.is_attached()) {
|
||||||
throw InvalidatedObjectException(m_object_schema->name,
|
throw InvalidatedObjectException(m_object_schema->name,
|
||||||
|
@ -638,6 +638,43 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
testRealmObjectForPrimaryKey: function() {
|
||||||
|
var realm = new Realm({schema: [schemas.IntPrimary, schemas.StringPrimary, schemas.TestObject]});
|
||||||
|
|
||||||
|
realm.write(function() {
|
||||||
|
realm.create('IntPrimaryObject', {primaryCol: 0, valueCol: 'val0'});
|
||||||
|
realm.create('IntPrimaryObject', {primaryCol: 1, valueCol: 'val1'});
|
||||||
|
|
||||||
|
realm.create('StringPrimaryObject', {primaryCol: '', valueCol: -1});
|
||||||
|
realm.create('StringPrimaryObject', {primaryCol: 'val0', valueCol: 0});
|
||||||
|
realm.create('StringPrimaryObject', {primaryCol: 'val1', valueCol: 1});
|
||||||
|
|
||||||
|
realm.create('TestObject', {doubleCol: 0});
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('IntPrimaryObject', -1), undefined);
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('IntPrimaryObject', 0).valueCol, 'val0');
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('IntPrimaryObject', 1).valueCol, 'val1');
|
||||||
|
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', 'invalid'), undefined);
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', '').valueCol, -1);
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', 'val0').valueCol, 0);
|
||||||
|
TestCase.assertEqual(realm.objectForPrimaryKey('StringPrimaryObject', 'val1').valueCol, 1);
|
||||||
|
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
realm.objectForPrimaryKey('TestObject', 0);
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
realm.objectForPrimaryKey();
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
realm.objectForPrimaryKey('IntPrimary');
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
realm.objectForPrimaryKey('InvalidClass', 0);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
testNotifications: function() {
|
testNotifications: function() {
|
||||||
var realm = new Realm({schema: []});
|
var realm = new Realm({schema: []});
|
||||||
var notificationCount = 0;
|
var notificationCount = 0;
|
||||||
|
@ -106,6 +106,15 @@ exports.IntPrimary = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.StringPrimary = {
|
||||||
|
name: 'StringPrimaryObject',
|
||||||
|
primaryKey: 'primaryCol',
|
||||||
|
properties: {
|
||||||
|
primaryCol: Realm.Types.STRING,
|
||||||
|
valueCol: Realm.Types.INT,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
exports.AllTypes = {
|
exports.AllTypes = {
|
||||||
name: 'AllTypesObject',
|
name: 'AllTypesObject',
|
||||||
primaryKey: 'primaryCol',
|
primaryKey: 'primaryCol',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user