mirror of
https://github.com/status-im/realm-js.git
synced 2025-02-03 18:24:04 +00:00
Add a Schema class, move lookup by name and internal-consistency checks there
This commit is contained in:
parent
d72d79bb05
commit
df6d6e8618
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "object_store.hpp"
|
#include "object_store.hpp"
|
||||||
|
|
||||||
|
#include "schema.hpp"
|
||||||
|
|
||||||
#include <realm/group.hpp>
|
#include <realm/group.hpp>
|
||||||
#include <realm/link_view.hpp>
|
#include <realm/link_view.hpp>
|
||||||
#include <realm/table.hpp>
|
#include <realm/table.hpp>
|
||||||
@ -147,17 +149,11 @@ static inline bool property_has_changed(Property const& p1, Property const& p2)
|
|||||||
|| p1.is_nullable != p2.is_nullable;
|
|| p1.is_nullable != p2.is_nullable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compare_by_name(ObjectSchema const& lft, ObjectSchema const& rgt) {
|
|
||||||
return lft.name < rgt.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectStore::verify_schema(Schema const& actual_schema, Schema& target_schema, bool allow_missing_tables) {
|
void ObjectStore::verify_schema(Schema const& actual_schema, Schema& target_schema, bool allow_missing_tables) {
|
||||||
std::sort(begin(target_schema), end(target_schema), compare_by_name);
|
|
||||||
|
|
||||||
std::vector<ObjectSchemaValidationException> errors;
|
std::vector<ObjectSchemaValidationException> errors;
|
||||||
for (auto &object_schema : target_schema) {
|
for (auto &object_schema : target_schema) {
|
||||||
auto matching_schema = std::lower_bound(begin(actual_schema), end(actual_schema), object_schema, compare_by_name);
|
auto matching_schema = actual_schema.find(object_schema);
|
||||||
if (matching_schema == end(actual_schema) || matching_schema->name != object_schema.name) {
|
if (matching_schema == actual_schema.end()) {
|
||||||
if (!allow_missing_tables) {
|
if (!allow_missing_tables) {
|
||||||
errors.emplace_back(ObjectSchemaValidationException(object_schema.name,
|
errors.emplace_back(ObjectSchemaValidationException(object_schema.name,
|
||||||
"Missing table for object type '" + object_schema.name + "'."));
|
"Missing table for object type '" + object_schema.name + "'."));
|
||||||
@ -165,7 +161,7 @@ void ObjectStore::verify_schema(Schema const& actual_schema, Schema& target_sche
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto more_errors = verify_object_schema(*matching_schema, object_schema, target_schema);
|
auto more_errors = verify_object_schema(*matching_schema, object_schema);
|
||||||
errors.insert(errors.end(), more_errors.begin(), more_errors.end());
|
errors.insert(errors.end(), more_errors.begin(), more_errors.end());
|
||||||
}
|
}
|
||||||
if (errors.size()) {
|
if (errors.size()) {
|
||||||
@ -174,18 +170,10 @@ void ObjectStore::verify_schema(Schema const& actual_schema, Schema& target_sche
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ObjectSchemaValidationException> ObjectStore::verify_object_schema(ObjectSchema const& table_schema,
|
std::vector<ObjectSchemaValidationException> ObjectStore::verify_object_schema(ObjectSchema const& table_schema,
|
||||||
ObjectSchema& target_schema,
|
ObjectSchema& target_schema) {
|
||||||
Schema const& schema) {
|
|
||||||
std::vector<ObjectSchemaValidationException> exceptions;
|
std::vector<ObjectSchemaValidationException> exceptions;
|
||||||
|
|
||||||
ObjectSchema cmp;
|
|
||||||
auto schema_contains_table = [&](std::string const& name) {
|
|
||||||
cmp.name = name;
|
|
||||||
return std::binary_search(begin(schema), end(schema), cmp, compare_by_name);
|
|
||||||
};
|
|
||||||
|
|
||||||
// check to see if properties are the same
|
// check to see if properties are the same
|
||||||
const Property *primary = nullptr;
|
|
||||||
for (auto& current_prop : table_schema.properties) {
|
for (auto& current_prop : table_schema.properties) {
|
||||||
auto target_prop = target_schema.property_for_name(current_prop.name);
|
auto target_prop = target_schema.property_for_name(current_prop.name);
|
||||||
|
|
||||||
@ -198,40 +186,6 @@ std::vector<ObjectSchemaValidationException> ObjectStore::verify_object_schema(O
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check object_type existence
|
|
||||||
if (current_prop.object_type.length() && !schema_contains_table(current_prop.object_type)) {
|
|
||||||
exceptions.emplace_back(MissingObjectTypeException(table_schema.name, current_prop));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check nullablity
|
|
||||||
if (current_prop.is_nullable) {
|
|
||||||
#if REALM_NULL_STRINGS == 1
|
|
||||||
if (current_prop.type == PropertyTypeArray || current_prop.type == PropertyTypeAny) {
|
|
||||||
#else
|
|
||||||
if (current_prop.type != PropertyTypeObject) {
|
|
||||||
#endif
|
|
||||||
exceptions.emplace_back(InvalidNullabilityException(table_schema.name, current_prop));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (current_prop.type == PropertyTypeObject) {
|
|
||||||
exceptions.emplace_back(InvalidNullabilityException(table_schema.name, current_prop));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check primary keys
|
|
||||||
if (current_prop.is_primary) {
|
|
||||||
if (primary) {
|
|
||||||
exceptions.emplace_back(DuplicatePrimaryKeysException(table_schema.name));
|
|
||||||
}
|
|
||||||
primary = ¤t_prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check indexable
|
|
||||||
if (current_prop.is_indexed) {
|
|
||||||
if (current_prop.type != PropertyTypeString && current_prop.type != PropertyTypeInt) {
|
|
||||||
exceptions.emplace_back(PropertyTypeNotIndexableException(table_schema.name, current_prop));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new property with aligned column
|
// create new property with aligned column
|
||||||
target_prop->table_column = current_prop.table_column;
|
target_prop->table_column = current_prop.table_column;
|
||||||
}
|
}
|
||||||
@ -347,8 +301,8 @@ bool ObjectStore::is_schema_at_version(const Group *group, uint64_t version) {
|
|||||||
|
|
||||||
bool ObjectStore::needs_update(Schema const& old_schema, Schema const& schema) {
|
bool ObjectStore::needs_update(Schema const& old_schema, Schema const& schema) {
|
||||||
for (auto const& target_schema : schema) {
|
for (auto const& target_schema : schema) {
|
||||||
auto matching_schema = std::lower_bound(begin(old_schema), end(old_schema), target_schema, compare_by_name);
|
auto matching_schema = old_schema.find(target_schema);
|
||||||
if (matching_schema == end(old_schema) || matching_schema->name != target_schema.name) {
|
if (matching_schema == end(old_schema)) {
|
||||||
// Table doesn't exist
|
// Table doesn't exist
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -405,14 +359,13 @@ bool ObjectStore::update_realm_with_schema(Group *group, Schema const& old_schem
|
|||||||
}
|
}
|
||||||
|
|
||||||
Schema ObjectStore::schema_from_group(const Group *group) {
|
Schema ObjectStore::schema_from_group(const Group *group) {
|
||||||
Schema schema;
|
std::vector<ObjectSchema> schema;
|
||||||
for (size_t i = 0; i < group->size(); i++) {
|
for (size_t i = 0; i < group->size(); i++) {
|
||||||
std::string object_type = object_type_for_table_name(group->get_table_name(i));
|
std::string object_type = object_type_for_table_name(group->get_table_name(i));
|
||||||
if (object_type.length()) {
|
if (object_type.length()) {
|
||||||
schema.emplace_back(group, object_type);
|
schema.emplace_back(group, object_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(begin(schema), end(schema), compare_by_name);
|
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class ObjectSchemaValidationException;
|
class ObjectSchemaValidationException;
|
||||||
using Schema = std::vector<ObjectSchema>;
|
class Schema;
|
||||||
|
|
||||||
class ObjectStore {
|
class ObjectStore {
|
||||||
public:
|
public:
|
||||||
@ -90,8 +90,7 @@ namespace realm {
|
|||||||
// updates the column mapping on the target_schema
|
// updates the column mapping on the target_schema
|
||||||
// returns array of validation errors
|
// returns array of validation errors
|
||||||
static std::vector<ObjectSchemaValidationException> verify_object_schema(ObjectSchema const& expected,
|
static std::vector<ObjectSchemaValidationException> verify_object_schema(ObjectSchema const& expected,
|
||||||
ObjectSchema &target_schema,
|
ObjectSchema &target_schema);
|
||||||
Schema const& schema);
|
|
||||||
|
|
||||||
// get primary key property name for object type
|
// get primary key property name for object type
|
||||||
static StringData get_primary_key_for_object(const Group *group, StringData object_type);
|
static StringData get_primary_key_for_object(const Group *group, StringData object_type);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "external_commit_helper.hpp"
|
#include "external_commit_helper.hpp"
|
||||||
#include "realm_delegate.hpp"
|
#include "realm_delegate.hpp"
|
||||||
|
#include "schema.hpp"
|
||||||
#include "transact_log_handler.hpp"
|
#include "transact_log_handler.hpp"
|
||||||
|
|
||||||
#include <realm/commit_log.hpp>
|
#include <realm/commit_log.hpp>
|
||||||
@ -45,6 +46,8 @@ Realm::Config::Config(const Config& c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Realm::Config::~Config() = default;
|
||||||
|
|
||||||
Realm::Config& Realm::Config::operator=(realm::Realm::Config const& c)
|
Realm::Config& Realm::Config::operator=(realm::Realm::Config const& c)
|
||||||
{
|
{
|
||||||
if (&c != this) {
|
if (&c != this) {
|
||||||
@ -154,6 +157,7 @@ SharedRealm Realm::get_shared_realm(Config config)
|
|||||||
if (realm->m_config.schema_version == ObjectStore::NotVersioned) {
|
if (realm->m_config.schema_version == ObjectStore::NotVersioned) {
|
||||||
throw UnitializedRealmException("Can't open an un-initialized Realm without a Schema");
|
throw UnitializedRealmException("Can't open an un-initialized Realm without a Schema");
|
||||||
}
|
}
|
||||||
|
target_schema->validate();
|
||||||
ObjectStore::verify_schema(*realm->m_config.schema, *target_schema, true);
|
ObjectStore::verify_schema(*realm->m_config.schema, *target_schema, true);
|
||||||
realm->m_config.schema = std::move(target_schema);
|
realm->m_config.schema = std::move(target_schema);
|
||||||
}
|
}
|
||||||
@ -171,6 +175,8 @@ SharedRealm Realm::get_shared_realm(Config config)
|
|||||||
|
|
||||||
bool Realm::update_schema(std::unique_ptr<Schema> schema, uint64_t version)
|
bool Realm::update_schema(std::unique_ptr<Schema> schema, uint64_t version)
|
||||||
{
|
{
|
||||||
|
schema->validate();
|
||||||
|
|
||||||
bool needs_update = !m_config.read_only && (m_config.schema_version != version || ObjectStore::needs_update(*m_config.schema, *schema));
|
bool needs_update = !m_config.read_only && (m_config.schema_version != version || ObjectStore::needs_update(*m_config.schema, *schema));
|
||||||
if (!needs_update) {
|
if (!needs_update) {
|
||||||
ObjectStore::verify_schema(*m_config.schema, *schema, m_config.read_only);
|
ObjectStore::verify_schema(*m_config.schema, *schema, m_config.read_only);
|
||||||
|
@ -56,6 +56,7 @@ namespace realm {
|
|||||||
Config() = default;
|
Config() = default;
|
||||||
Config(Config&&) = default;
|
Config(Config&&) = default;
|
||||||
Config(const Config& c);
|
Config(const Config& c);
|
||||||
|
~Config();
|
||||||
|
|
||||||
Config& operator=(Config const&);
|
Config& operator=(Config const&);
|
||||||
Config& operator=(Config&&) = default;
|
Config& operator=(Config&&) = default;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user