cleaup schema initialization
This commit is contained in:
parent
e9379491d6
commit
373375fa1b
|
@ -43,8 +43,6 @@ namespace realm {
|
||||||
Property *primary_key_property() {
|
Property *primary_key_property() {
|
||||||
return property_for_name(primary_key);
|
return property_for_name(primary_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,26 @@ static inline bool property_has_changed(Property &p1, Property &p2) {
|
||||||
return p1.type != p2.type || p1.name != p2.name || p1.object_type != p2.object_type || p1.is_nullable != p2.is_nullable;
|
return p1.type != p2.type || p1.name != p2.name || p1.object_type != p2.object_type || p1.is_nullable != p2.is_nullable;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ObjectSchemaValidationException> ObjectStore::validate_object_schema(Group *group, ObjectSchema &target_schema) {
|
void ObjectStore::verify_schema(Group *group, Schema &target_schema, bool allow_missing_tables) {
|
||||||
|
std::vector<ObjectSchemaValidationException> errors;
|
||||||
|
for (auto &object_schema : target_schema) {
|
||||||
|
if (!table_for_object_type(group, object_schema.first)) {
|
||||||
|
if (!allow_missing_tables) {
|
||||||
|
errors.emplace_back(ObjectSchemaValidationException(object_schema.first,
|
||||||
|
"Missing table for object type '" + object_schema.first + "'."));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto more_errors = verify_object_schema(group, object_schema.second, target_schema);
|
||||||
|
errors.insert(errors.end(), more_errors.begin(), more_errors.end());
|
||||||
|
}
|
||||||
|
if (errors.size()) {
|
||||||
|
throw SchemaValidationException(errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ObjectSchemaValidationException> ObjectStore::verify_object_schema(Group *group, ObjectSchema &target_schema, Schema &schema) {
|
||||||
std::vector<ObjectSchemaValidationException> exceptions;
|
std::vector<ObjectSchemaValidationException> exceptions;
|
||||||
ObjectSchema table_schema(group, target_schema.name);
|
ObjectSchema table_schema(group, target_schema.name);
|
||||||
|
|
||||||
|
@ -156,6 +175,10 @@ std::vector<ObjectSchemaValidationException> ObjectStore::validate_object_schema
|
||||||
exceptions.emplace_back(MismatchedPropertiesException(table_schema.name, current_prop, *target_prop));
|
exceptions.emplace_back(MismatchedPropertiesException(table_schema.name, current_prop, *target_prop));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (current_prop.object_type.length() && schema.find(current_prop.object_type) == schema.end()) {
|
||||||
|
exceptions.emplace_back(InvalidPropertyException(table_schema.name, current_prop,
|
||||||
|
"Target type '" + current_prop.object_type + "' doesn't exist for property '" + current_prop.name + "',"));
|
||||||
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -300,12 +323,7 @@ bool ObjectStore::update_realm_with_schema(Group *group,
|
||||||
bool changed = create_metadata_tables(group);
|
bool changed = create_metadata_tables(group);
|
||||||
changed = create_tables(group, schema, migrating) || changed;
|
changed = create_tables(group, schema, migrating) || changed;
|
||||||
|
|
||||||
for (auto& target_schema : schema) {
|
verify_schema(group, schema);
|
||||||
auto errors = validate_object_schema(group, target_schema.second);
|
|
||||||
if (errors.size()) {
|
|
||||||
throw ObjectSchemaValidationException(target_schema.first, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = update_indexes(group, schema) || changed;
|
changed = update_indexes(group, schema) || changed;
|
||||||
|
|
||||||
|
@ -419,10 +437,10 @@ DuplicatePrimaryKeyValueException::DuplicatePrimaryKeyValueException(std::string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ObjectSchemaValidationException::ObjectSchemaValidationException(std::string object_type, std::vector<ObjectSchemaValidationException> errors) :
|
SchemaValidationException::SchemaValidationException(std::vector<ObjectSchemaValidationException> errors) :
|
||||||
m_object_type(object_type), m_validation_errors(errors)
|
m_validation_errors(errors)
|
||||||
{
|
{
|
||||||
m_what ="Migration is required for object type '" + object_type + "' due to the following errors: ";
|
m_what ="Migration is required due to the following errors: ";
|
||||||
for (auto error : errors) {
|
for (auto error : errors) {
|
||||||
m_what += std::string("\n- ") + error.what();
|
m_what += std::string("\n- ") + error.what();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,10 @@ namespace realm {
|
||||||
// checks if the schema in the group is at the given version
|
// checks if the schema in the group is at the given version
|
||||||
static bool is_schema_at_version(realm::Group *group, uint64_t version);
|
static bool is_schema_at_version(realm::Group *group, uint64_t version);
|
||||||
|
|
||||||
// verify a target schema against its table, setting the table_column property on each schema object
|
// verify a target schema against tables in the given group
|
||||||
// updates the column mapping on the target_schema
|
// updates the column mapping on all ObjectSchema properties
|
||||||
// if no table is provided it is fetched from the group
|
// throws if the schema is invalid or does not match tables in the given group
|
||||||
// returns array of validation errors
|
static void verify_schema(Group *group, Schema &target_schema, bool allow_missing_tables = false);
|
||||||
static std::vector<ObjectSchemaValidationException> validate_object_schema(Group *group, ObjectSchema &target_schema);
|
|
||||||
|
|
||||||
// updates the target_column member for all properties based on the column indexes in the passed in group
|
// updates the target_column member for all properties based on the column indexes in the passed in group
|
||||||
static void update_column_mapping(Group *group, ObjectSchema &target_schema);
|
static void update_column_mapping(Group *group, ObjectSchema &target_schema);
|
||||||
|
@ -90,6 +89,11 @@ namespace realm {
|
||||||
// if update existing is true, updates existing tables, otherwise only adds and initializes new tables
|
// if update existing is true, updates existing tables, otherwise only adds and initializes new tables
|
||||||
static bool create_tables(realm::Group *group, Schema &target_schema, bool update_existing);
|
static bool create_tables(realm::Group *group, Schema &target_schema, bool update_existing);
|
||||||
|
|
||||||
|
// verify a target schema against its table, setting the table_column property on each schema object
|
||||||
|
// updates the column mapping on the target_schema
|
||||||
|
// returns array of validation errors
|
||||||
|
static std::vector<ObjectSchemaValidationException> verify_object_schema(Group *group, ObjectSchema &target_schema, Schema &schema);
|
||||||
|
|
||||||
// get primary key property name for object type
|
// get primary key property name for object type
|
||||||
static StringData get_primary_key_for_object(Group *group, StringData object_type);
|
static StringData get_primary_key_for_object(Group *group, StringData object_type);
|
||||||
|
|
||||||
|
@ -142,12 +146,18 @@ namespace realm {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Schema validation exceptions
|
// Schema validation exceptions
|
||||||
|
class SchemaValidationException : public ObjectStoreException {
|
||||||
|
public:
|
||||||
|
SchemaValidationException(std::vector<ObjectSchemaValidationException> errors);
|
||||||
|
private:
|
||||||
|
std::vector<ObjectSchemaValidationException> m_validation_errors;
|
||||||
|
};
|
||||||
|
|
||||||
class ObjectSchemaValidationException : public ObjectStoreException {
|
class ObjectSchemaValidationException : public ObjectStoreException {
|
||||||
public:
|
public:
|
||||||
ObjectSchemaValidationException(std::string object_type) : m_object_type(object_type) {}
|
ObjectSchemaValidationException(std::string object_type) : m_object_type(object_type) {}
|
||||||
ObjectSchemaValidationException(std::string object_type, std::vector<ObjectSchemaValidationException> errors);
|
ObjectSchemaValidationException(std::string object_type, std::string message) :
|
||||||
private:
|
m_object_type(object_type) { m_what = message; }
|
||||||
std::vector<ObjectSchemaValidationException> m_validation_errors;
|
|
||||||
protected:
|
protected:
|
||||||
std::string m_object_type;
|
std::string m_object_type;
|
||||||
};
|
};
|
||||||
|
@ -193,6 +203,14 @@ namespace realm {
|
||||||
private:
|
private:
|
||||||
std::string m_primary;
|
std::string m_primary;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class InvalidPropertyException : public ObjectSchemaValidationException {
|
||||||
|
public:
|
||||||
|
InvalidPropertyException(std::string object_type, Property &property, std::string message) :
|
||||||
|
ObjectSchemaValidationException(object_type), m_property(property) { m_what = message; }
|
||||||
|
private:
|
||||||
|
Property m_property;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(REALM_OBJECT_STORE_HPP) */
|
#endif /* defined(REALM_OBJECT_STORE_HPP) */
|
||||||
|
|
|
@ -107,23 +107,17 @@ SharedRealm Realm::get_shared_realm(Config &config)
|
||||||
// we want to ensure we are only initializing a single realm at a time
|
// we want to ensure we are only initializing a single realm at a time
|
||||||
std::lock_guard<std::mutex> lock(s_init_mutex);
|
std::lock_guard<std::mutex> lock(s_init_mutex);
|
||||||
|
|
||||||
if (!config.schema) {
|
uint64_t old_version = ObjectStore::get_schema_version(realm->read_group());
|
||||||
uint64_t version = ObjectStore::get_schema_version(realm->read_group());
|
if (!realm->m_config.schema) {
|
||||||
if (version == ObjectStore::NotVersioned) {
|
|
||||||
InvalidSchemaVersionException(ObjectStore::NotVersioned, ObjectStore::NotVersioned);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get schema from group and skip validation
|
// get schema from group and skip validation
|
||||||
realm->m_config.schema_version = version;
|
realm->m_config.schema_version = old_version;
|
||||||
realm->m_config.schema = std::make_unique<Schema>(ObjectStore::schema_from_group(realm->read_group()));
|
realm->m_config.schema = std::make_unique<Schema>(ObjectStore::schema_from_group(realm->read_group()));
|
||||||
}
|
}
|
||||||
else if (config.read_only) {
|
else if (realm->m_config.read_only) {
|
||||||
// for read-only validate all existing tables
|
if (old_version == ObjectStore::NotVersioned) {
|
||||||
for (auto &object_schema : *realm->m_config.schema) {
|
throw UnitializedRealmException("Can't open an un-initizliazed Realm without a Schema");
|
||||||
if (ObjectStore::table_for_object_type(realm->read_group(), object_schema.first)) {
|
|
||||||
ObjectStore::validate_object_schema(realm->read_group(), object_schema.second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ObjectStore::verify_schema(realm->read_group(), *realm->m_config.schema, true);
|
||||||
}
|
}
|
||||||
else if(auto existing = s_global_cache.get_any_realm(realm->config().path)) {
|
else if(auto existing = s_global_cache.get_any_realm(realm->config().path)) {
|
||||||
// if there is an existing realm at the current path steal its schema/column mapping
|
// if there is an existing realm at the current path steal its schema/column mapping
|
||||||
|
@ -132,7 +126,7 @@ SharedRealm Realm::get_shared_realm(Config &config)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// its a non-cached realm so update/migrate if needed
|
// its a non-cached realm so update/migrate if needed
|
||||||
realm->update_schema(*realm->m_config.schema, config.schema_version);
|
realm->update_schema(*realm->m_config.schema, realm->m_config.schema_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_global_cache.cache_realm(realm, realm->m_thread_id);
|
s_global_cache.cache_realm(realm, realm->m_thread_id);
|
||||||
|
@ -151,7 +145,7 @@ bool Realm::update_schema(Schema &schema, uint64_t version)
|
||||||
m_config.schema_version = version;
|
m_config.schema_version = version;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (ObjectStore::realm_requires_update(read_group(), version, schema)) {
|
if (!m_config.read_only && ObjectStore::realm_requires_update(read_group(), version, schema)) {
|
||||||
// keep old copy to pass to migration function
|
// keep old copy to pass to migration function
|
||||||
old_config.read_only = true;
|
old_config.read_only = true;
|
||||||
SharedRealm old_realm = SharedRealm(new Realm(old_config)), updated_realm = shared_from_this();
|
SharedRealm old_realm = SharedRealm(new Realm(old_config)), updated_realm = shared_from_this();
|
||||||
|
@ -164,13 +158,7 @@ bool Realm::update_schema(Schema &schema, uint64_t version)
|
||||||
commit_transaction();
|
commit_transaction();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// verify all types
|
ObjectStore::verify_schema(read_group(), *m_config.schema, m_config.read_only);
|
||||||
for (auto& target_schema : *m_config.schema) {
|
|
||||||
auto errors = ObjectStore::validate_object_schema(read_group(), target_schema.second);
|
|
||||||
if (errors.size()) {
|
|
||||||
throw ObjectSchemaValidationException(target_schema.first, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
@ -409,4 +397,3 @@ void RealmCache::cache_realm(SharedRealm &realm, std::thread::id thread_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,12 @@ namespace realm {
|
||||||
public:
|
public:
|
||||||
IncorrectThreadException(std::string message) : std::runtime_error(message) {}
|
IncorrectThreadException(std::string message) : std::runtime_error(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UnitializedRealmException : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(REALM_REALM_HPP) */
|
#endif /* defined(REALM_REALM_HPP) */
|
||||||
|
|
Loading…
Reference in New Issue