Add support for the concept of computed properties.
This commit is contained in:
parent
64e733e4d7
commit
abca7c26e1
|
@ -43,9 +43,9 @@ ASSERT_PROPERTY_TYPE_VALUE(Array, LinkList);
|
|||
ObjectSchema::ObjectSchema() = default;
|
||||
ObjectSchema::~ObjectSchema() = default;
|
||||
|
||||
ObjectSchema::ObjectSchema(std::string name, std::string primary_key, std::initializer_list<Property> properties)
|
||||
ObjectSchema::ObjectSchema(std::string name, std::string primary_key, std::initializer_list<Property> persisted_properties)
|
||||
: name(std::move(name))
|
||||
, properties(properties)
|
||||
, persisted_properties(persisted_properties)
|
||||
, primary_key(std::move(primary_key))
|
||||
{
|
||||
set_primary_key_property();
|
||||
|
@ -55,7 +55,7 @@ ObjectSchema::ObjectSchema(const Group *group, const std::string &name) : name(n
|
|||
ConstTableRef table = ObjectStore::table_for_object_type(group, name);
|
||||
|
||||
size_t count = table->get_column_count();
|
||||
properties.reserve(count);
|
||||
persisted_properties.reserve(count);
|
||||
for (size_t col = 0; col < count; col++) {
|
||||
Property property;
|
||||
property.name = table->get_column_name(col).data();
|
||||
|
@ -69,7 +69,7 @@ ObjectSchema::ObjectSchema(const Group *group, const std::string &name) : name(n
|
|||
ConstTableRef linkTable = table->get_link_target(col);
|
||||
property.object_type = ObjectStore::object_type_for_table_name(linkTable->get_name().data());
|
||||
}
|
||||
properties.push_back(std::move(property));
|
||||
persisted_properties.push_back(std::move(property));
|
||||
}
|
||||
|
||||
primary_key = realm::ObjectStore::get_primary_key_for_object(group, name);
|
||||
|
@ -77,7 +77,12 @@ ObjectSchema::ObjectSchema(const Group *group, const std::string &name) : name(n
|
|||
}
|
||||
|
||||
Property *ObjectSchema::property_for_name(StringData name) {
|
||||
for (auto& prop : properties) {
|
||||
for (auto& prop : persisted_properties) {
|
||||
if (StringData(prop.name) == name) {
|
||||
return ∝
|
||||
}
|
||||
}
|
||||
for (auto& prop : computed_properties) {
|
||||
if (StringData(prop.name) == name) {
|
||||
return ∝
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ struct Property;
|
|||
class ObjectSchema {
|
||||
public:
|
||||
ObjectSchema();
|
||||
ObjectSchema(std::string name, std::string primary_key, std::initializer_list<Property> properties);
|
||||
ObjectSchema(std::string name, std::string primary_key, std::initializer_list<Property> persisted_properties);
|
||||
~ObjectSchema();
|
||||
|
||||
// create object schema from existing table
|
||||
|
@ -39,7 +39,8 @@ public:
|
|||
ObjectSchema(const Group *group, const std::string &name);
|
||||
|
||||
std::string name;
|
||||
std::vector<Property> properties;
|
||||
std::vector<Property> persisted_properties;
|
||||
std::vector<Property> computed_properties;
|
||||
std::string primary_key;
|
||||
|
||||
Property *property_for_name(StringData name);
|
||||
|
|
|
@ -180,7 +180,7 @@ std::vector<ObjectSchemaValidationException> ObjectStore::verify_object_schema(O
|
|||
std::vector<ObjectSchemaValidationException> exceptions;
|
||||
|
||||
// check to see if properties are the same
|
||||
for (auto& current_prop : table_schema.properties) {
|
||||
for (auto& current_prop : table_schema.persisted_properties) {
|
||||
auto target_prop = target_schema.property_for_name(current_prop.name);
|
||||
|
||||
if (!target_prop) {
|
||||
|
@ -202,7 +202,7 @@ std::vector<ObjectSchemaValidationException> ObjectStore::verify_object_schema(O
|
|||
}
|
||||
|
||||
// check for new missing properties
|
||||
for (auto& target_prop : target_schema.properties) {
|
||||
for (auto& target_prop : target_schema.persisted_properties) {
|
||||
if (!table_schema.property_for_name(target_prop.name)) {
|
||||
exceptions.emplace_back(ExtraPropertyException(table_schema.name, target_prop));
|
||||
}
|
||||
|
@ -270,10 +270,10 @@ void ObjectStore::create_tables(Group *group, Schema &target_schema, bool update
|
|||
for (auto& target_object_schema : to_update) {
|
||||
TableRef table = table_for_object_type(group, target_object_schema->name);
|
||||
ObjectSchema current_schema(group, target_object_schema->name);
|
||||
std::vector<Property> &target_props = target_object_schema->properties;
|
||||
std::vector<Property> &target_props = target_object_schema->persisted_properties;
|
||||
|
||||
// handle columns changing from required to optional
|
||||
for (auto& current_prop : current_schema.properties) {
|
||||
for (auto& current_prop : current_schema.persisted_properties) {
|
||||
auto target_prop = target_object_schema->property_for_name(current_prop.name);
|
||||
if (!target_prop || !property_can_be_migrated_to_nullable(current_prop, *target_prop))
|
||||
continue;
|
||||
|
@ -292,13 +292,13 @@ void ObjectStore::create_tables(Group *group, Schema &target_schema, bool update
|
|||
|
||||
// remove extra columns
|
||||
size_t deleted = 0;
|
||||
for (auto& current_prop : current_schema.properties) {
|
||||
for (auto& current_prop : current_schema.persisted_properties) {
|
||||
current_prop.table_column -= deleted;
|
||||
|
||||
auto target_prop = target_object_schema->property_for_name(current_prop.name);
|
||||
if (!target_prop || (property_has_changed(current_prop, *target_prop)
|
||||
&& !property_can_be_migrated_to_nullable(current_prop, *target_prop))) {
|
||||
if (deleted == current_schema.properties.size() - 1) {
|
||||
if (deleted == current_schema.persisted_properties.size() - 1) {
|
||||
// We're about to remove the last column from the table. Insert a placeholder column to preserve
|
||||
// the number of rows in the table for the addition of new columns below.
|
||||
table->add_column(type_Bool, "placeholder");
|
||||
|
@ -377,14 +377,14 @@ bool ObjectStore::needs_update(Schema const& old_schema, Schema const& schema) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (matching_schema->properties.size() != target_schema.properties.size()) {
|
||||
if (matching_schema->persisted_properties.size() != target_schema.persisted_properties.size()) {
|
||||
// If the number of properties don't match then a migration is required
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all of the property indexes are up to date
|
||||
for (size_t i = 0, count = target_schema.properties.size(); i < count; ++i) {
|
||||
if (target_schema.properties[i].is_indexed != matching_schema->properties[i].is_indexed) {
|
||||
for (size_t i = 0, count = target_schema.persisted_properties.size(); i < count; ++i) {
|
||||
if (target_schema.persisted_properties[i].is_indexed != matching_schema->persisted_properties[i].is_indexed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ bool ObjectStore::update_indexes(Group *group, Schema &schema) {
|
|||
continue;
|
||||
}
|
||||
|
||||
for (auto& property : object_schema.properties) {
|
||||
for (auto& property : object_schema.persisted_properties) {
|
||||
if (property.requires_index() == table->has_search_index(property.table_column)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,11 @@ void Schema::validate() const
|
|||
std::vector<ObjectSchemaValidationException> exceptions;
|
||||
for (auto const& object : *this) {
|
||||
const Property *primary = nullptr;
|
||||
for (auto const& prop : object.properties) {
|
||||
|
||||
std::vector<Property> all_properties = object.persisted_properties;
|
||||
all_properties.insert(all_properties.end(), object.computed_properties.begin(), object.computed_properties.end());
|
||||
|
||||
for (auto const& prop : all_properties) {
|
||||
// check object_type existence
|
||||
if (!prop.object_type.empty() && find(prop.object_type) == end()) {
|
||||
exceptions.emplace_back(MissingObjectTypeException(object.name, prop));
|
||||
|
|
Loading…
Reference in New Issue