cleaup schema initialization
This commit is contained in:
parent
e9379491d6
commit
373375fa1b
|
@ -43,8 +43,6 @@ namespace realm {
|
|||
Property *primary_key_property() {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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));
|
||||
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
|
||||
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);
|
||||
changed = create_tables(group, schema, migrating) || changed;
|
||||
|
||||
for (auto& target_schema : schema) {
|
||||
auto errors = validate_object_schema(group, target_schema.second);
|
||||
if (errors.size()) {
|
||||
throw ObjectSchemaValidationException(target_schema.first, errors);
|
||||
}
|
||||
}
|
||||
verify_schema(group, schema);
|
||||
|
||||
changed = update_indexes(group, schema) || changed;
|
||||
|
||||
|
@ -419,10 +437,10 @@ DuplicatePrimaryKeyValueException::DuplicatePrimaryKeyValueException(std::string
|
|||
};
|
||||
|
||||
|
||||
ObjectSchemaValidationException::ObjectSchemaValidationException(std::string object_type, std::vector<ObjectSchemaValidationException> errors) :
|
||||
m_object_type(object_type), m_validation_errors(errors)
|
||||
SchemaValidationException::SchemaValidationException(std::vector<ObjectSchemaValidationException> 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) {
|
||||
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
|
||||
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
|
||||
// updates the column mapping on the target_schema
|
||||
// if no table is provided it is fetched from the group
|
||||
// returns array of validation errors
|
||||
static std::vector<ObjectSchemaValidationException> validate_object_schema(Group *group, ObjectSchema &target_schema);
|
||||
// verify a target schema against tables in the given group
|
||||
// updates the column mapping on all ObjectSchema properties
|
||||
// throws if the schema is invalid or does not match tables in the given group
|
||||
static void verify_schema(Group *group, Schema &target_schema, bool allow_missing_tables = false);
|
||||
|
||||
// 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);
|
||||
|
@ -90,6 +89,11 @@ namespace realm {
|
|||
// 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);
|
||||
|
||||
// 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
|
||||
static StringData get_primary_key_for_object(Group *group, StringData object_type);
|
||||
|
||||
|
@ -142,12 +146,18 @@ namespace realm {
|
|||
};
|
||||
|
||||
// Schema validation exceptions
|
||||
class SchemaValidationException : public ObjectStoreException {
|
||||
public:
|
||||
SchemaValidationException(std::vector<ObjectSchemaValidationException> errors);
|
||||
private:
|
||||
std::vector<ObjectSchemaValidationException> m_validation_errors;
|
||||
};
|
||||
|
||||
class ObjectSchemaValidationException : public ObjectStoreException {
|
||||
public:
|
||||
ObjectSchemaValidationException(std::string object_type) : m_object_type(object_type) {}
|
||||
ObjectSchemaValidationException(std::string object_type, std::vector<ObjectSchemaValidationException> errors);
|
||||
private:
|
||||
std::vector<ObjectSchemaValidationException> m_validation_errors;
|
||||
ObjectSchemaValidationException(std::string object_type, std::string message) :
|
||||
m_object_type(object_type) { m_what = message; }
|
||||
protected:
|
||||
std::string m_object_type;
|
||||
};
|
||||
|
@ -193,6 +203,14 @@ namespace realm {
|
|||
private:
|
||||
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) */
|
||||
|
|
|
@ -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
|
||||
std::lock_guard<std::mutex> lock(s_init_mutex);
|
||||
|
||||
if (!config.schema) {
|
||||
uint64_t version = ObjectStore::get_schema_version(realm->read_group());
|
||||
if (version == ObjectStore::NotVersioned) {
|
||||
InvalidSchemaVersionException(ObjectStore::NotVersioned, ObjectStore::NotVersioned);
|
||||
}
|
||||
|
||||
uint64_t old_version = ObjectStore::get_schema_version(realm->read_group());
|
||||
if (!realm->m_config.schema) {
|
||||
// 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()));
|
||||
}
|
||||
else if (config.read_only) {
|
||||
// for read-only validate all existing tables
|
||||
for (auto &object_schema : *realm->m_config.schema) {
|
||||
if (ObjectStore::table_for_object_type(realm->read_group(), object_schema.first)) {
|
||||
ObjectStore::validate_object_schema(realm->read_group(), object_schema.second);
|
||||
}
|
||||
else if (realm->m_config.read_only) {
|
||||
if (old_version == ObjectStore::NotVersioned) {
|
||||
throw UnitializedRealmException("Can't open an un-initizliazed Realm without a Schema");
|
||||
}
|
||||
ObjectStore::verify_schema(realm->read_group(), *realm->m_config.schema, true);
|
||||
}
|
||||
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
|
||||
|
@ -132,7 +126,7 @@ SharedRealm Realm::get_shared_realm(Config &config)
|
|||
}
|
||||
else {
|
||||
// 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);
|
||||
|
@ -151,7 +145,7 @@ bool Realm::update_schema(Schema &schema, uint64_t version)
|
|||
m_config.schema_version = version;
|
||||
|
||||
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
|
||||
old_config.read_only = true;
|
||||
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();
|
||||
}
|
||||
else {
|
||||
// verify all types
|
||||
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);
|
||||
}
|
||||
}
|
||||
ObjectStore::verify_schema(read_group(), *m_config.schema, m_config.read_only);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -409,4 +397,3 @@ void RealmCache::cache_realm(SharedRealm &realm, std::thread::id thread_id)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -183,6 +183,12 @@ namespace realm {
|
|||
public:
|
||||
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) */
|
||||
|
|
Loading…
Reference in New Issue