update dependencies

This commit is contained in:
Folling 2025-01-02 09:39:58 +01:00
parent e6233cf3f2
commit ef27673846
No known key found for this signature in database
21 changed files with 800 additions and 370 deletions

View file

@ -4,13 +4,28 @@
#include <ikarus/errors.h>
#include <ikarus/errors.hpp>
#include <ikarus/objects/blueprint.h>
#include <ikarus/objects/entity.h>
#include <ikarus/objects/property.h>
#include <ikarus/persistence/project.hpp>
IkarusEntity::IkarusEntity(struct IkarusProject * project, int64_t id):
project{project},
id{id} {}
bool ikarus_entity_exists(IkarusEntity * entity, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(entity, false);
IKARUS_VTRYRV_OR_FAIL(
auto exists,
false,
"failed to check whether entity exists: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<bool>("SELECT EXISTS(SELECT 1 FROM `entities` WHERE `id` = ?)", entity->id)
);
return exists;
}
IkarusEntity * ikarus_entity_create(
struct IkarusProject * project,
char const * name,
@ -31,98 +46,83 @@ IkarusEntity * ikarus_entity_create(
return new IkarusEntity{project, id};
}
void ikarus_entity_delete(
IkarusEntity * entity,
IkarusEntityDeleteFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
void ikarus_entity_delete(IkarusEntity * entity, IkarusEntityDeleteFlags flags, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_TRYRV_OR_FAIL(
IKARUS_VOID_RETURN,
"failed to delete entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db
->execute("DELETE FROM `entities` WHERE `id` = ?", entity->id)
entity->project->db->execute("DELETE FROM `entities` WHERE `id` = ?", entity->id)
);
delete entity;
}
IkarusEntity * ikarus_entity_copy(
IkarusEntity * entity,
IkarusEntityCopyFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
IkarusEntity * ikarus_entity_copy(IkarusEntity * entity, IkarusEntityCopyFlags flags, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VTRYRV_OR_FAIL(
auto id,
nullptr,
"failed to copy entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->transact(
[entity](auto * db)
-> cppbase::Result<int64_t, sqlitecpp::TransactionError> {
TRY(entity->project->db->execute(
"INSERT INTO `entities`(`name`) "
"SELECT `name` FROM `entities` WHERE `id` = ?",
entity->id
));
entity->project->db->transact([entity](auto * db) -> cppbase::Result<int64_t, sqlitecpp::TransactionError> {
CPPBASE_TRY(entity->project->db->execute(
"INSERT INTO `entities`(`name`) "
"SELECT `name` FROM `entities` WHERE `id` = ?",
entity->id
));
TRY(entity->project->db->execute(
"INSERT INTO `entity_values`(`entity`, `name`, `value`) "
"SELECT ?1, `name`, `value` FROM `entity_values` WHERE "
"`entity` = ?1",
entity->id
))
CPPBASE_TRY(entity->project->db->execute(
"INSERT INTO `entity_values`(`entity`, `name`, `value`) "
"SELECT ?1, `name`, `value` FROM `entity_values` WHERE "
"`entity` = ?1",
entity->id
))
TRY(entity->project->db->execute(
"INSERT INTO `entity_property_values`(`entity`, `property`, `value`) "
"SELECT ?1, `property`, `value` FROM `entity_property_values` "
"WHERE `entity` = ?1",
entity->id
))
CPPBASE_TRY(entity->project->db->execute(
"INSERT INTO `entity_property_values`(`entity`, `property`, `value`) "
"SELECT ?1, `property`, `value` FROM `entity_property_values` "
"WHERE `entity` = ?1",
entity->id
))
TRY(entity->project->db->execute(
"INSERT INTO `entity_blueprint_links`(`entity`, `blueprint`) "
"SELECT ?1, `property`, `value` FROM `entity_property_values` "
"WHERE `entity` = ?1",
entity->id
))
CPPBASE_TRY(entity->project->db->execute(
"INSERT INTO `entity_blueprint_links`(`entity`, `blueprint`) "
"SELECT ?1, `property`, `value` FROM `entity_property_values` "
"WHERE `entity` = ?1",
entity->id
))
return cppbase::ok(entity->project->db->last_insert_rowid());
}
)
return cppbase::ok(entity->project->db->last_insert_rowid());
})
);
return new IkarusEntity{entity->project, id};
}
IkarusProject *
ikarus_entity_get_project(IkarusEntity * entity, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
IkarusProject * ikarus_entity_get_project(IkarusEntity * entity, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
return entity->project;
}
char const *
ikarus_entity_get_name(IkarusEntity * entity, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
char const * ikarus_entity_get_name(IkarusEntity * entity, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VTRYRV_OR_FAIL(
auto name,
nullptr,
"failed to get name for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<char const *>(
"SELECT `name` FROM `entities` WHERE `id` = ?",
entity->id
)
entity->project->db->query_one<char const *>("SELECT `name` FROM `entities` WHERE `id` = ?", entity->id)
);
return name;
@ -134,33 +134,63 @@ void ikarus_entity_set_name(
IkarusEntitySetNameFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_FAIL_IF_NAME_INVALID(name, IKARUS_VOID_RETURN);
IKARUS_TRYRV_OR_FAIL(
IKARUS_VOID_RETURN,
"failed to set name for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->execute(
"UPDATE `entities` SET `name` = ? WHERE `id` = ?",
name,
entity->id
)
entity->project->db->execute("UPDATE `entities` SET `name` = ? WHERE `id` = ?", name, entity->id)
);
}
struct IkarusBlueprint ** ikarus_entity_get_linked_blueprints(
bool ikarus_entity_is_linked_to_blueprint(
IkarusEntity * entity,
size_t * size_out,
struct IkarusBlueprint * blueprint,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
IKARUS_FAIL_IF_NULL(size_out, nullptr);
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_ASCERTAIN(
false,
"blueprint doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_blueprint_exists,
blueprint
);
auto count = ikarus_entity_get_linked_blueprints_count(entity, error_out);
IKARUS_FAIL_IF_ERROR(nullptr);
IKARUS_FAIL_IF(
entity->project != blueprint->project,
false,
"blueprint does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_VTRYRV_OR_FAIL(
auto exists,
false,
"failed to check if entity is linked to blueprint: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<bool>(
"SELECT EXISTS(SELECT 1 FROM `entity_blueprint_links` WHERE `entity` = ? AND `blueprint` = ?)",
entity->id,
blueprint->id
)
);
return exists;
}
struct IkarusBlueprint **
ikarus_entity_get_linked_blueprints(IkarusEntity * entity, size_t * size_out, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VCALL(auto count, false, ikarus_entity_get_linked_blueprints_count, entity);
std::int64_t ids[count];
@ -189,22 +219,16 @@ struct IkarusBlueprint ** ikarus_entity_get_linked_blueprints(
return blueprints;
}
size_t ikarus_entity_get_linked_blueprints_count(
IkarusEntity * entity,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, 0);
IKARUS_FAIL_IF_NOT_EXIST(entity, 0);
size_t ikarus_entity_get_linked_blueprints_count(IkarusEntity * entity, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VTRYRV_OR_FAIL(
auto count,
0,
"failed to get linked blueprints count for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<std::int64_t>(
"SELECT COUNT(*) FROM `entity_blueprint_links` WHERE `entity` = ?",
entity->id
)
entity->project->db
->query_one<std::int64_t>("SELECT COUNT(*) FROM `entity_blueprint_links` WHERE `entity` = ?", entity->id)
);
return count;
@ -216,10 +240,28 @@ void ikarus_entity_link_blueprint(
IkarusEntityLinkBlueprintFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NULL(blueprint, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(blueprint, IKARUS_VOID_RETURN);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"blueprint doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_blueprint_exists,
blueprint
);
IKARUS_FAIL_IF(
entity->project != blueprint->project,
IKARUS_VOID_RETURN,
"blueprint does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_TRYRV_OR_FAIL(
IKARUS_VOID_RETURN,
@ -239,10 +281,28 @@ void ikarus_entity_unlink_blueprint(
IkarusEntityUnlinkBlueprintFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NULL(blueprint, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(blueprint, IKARUS_VOID_RETURN);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"blueprint doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_blueprint_exists,
blueprint
);
IKARUS_FAIL_IF(
entity->project != blueprint->project,
IKARUS_VOID_RETURN,
"blueprint does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_TRYRV_OR_FAIL(
IKARUS_VOID_RETURN,
@ -256,13 +316,28 @@ void ikarus_entity_unlink_blueprint(
);
}
IkarusEntityValue * ikarus_entity_get_values(
IkarusEntity * entity,
size_t * size_out,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
bool ikarus_entity_has_value(IkarusEntity * entity, char const * name, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(name, false);
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VTRYRV_OR_FAIL(
auto exists,
false,
"failed to check if entity has value: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<bool>(
"SELECT EXISTS(SELECT 1 FROM `entity_values` WHERE `entity` = ? AND `name` = ?)",
entity->id,
name
)
);
return exists;
}
IkarusEntityValue * ikarus_entity_get_values(IkarusEntity * entity, size_t * size_out, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VTRYRV_OR_FAIL(
auto values_plain,
@ -277,17 +352,9 @@ IkarusEntityValue * ikarus_entity_get_values(
IkarusEntityValue * values = new IkarusEntityValue[values_plain.size()];
std::transform(
std::cbegin(values_plain),
std::cend(values_plain),
values,
[](auto const & tuple) {
return IkarusEntityValue{
tuple.template get<0>(),
tuple.template get<1>()
};
}
);
std::transform(std::cbegin(values_plain), std::cend(values_plain), values, [](auto const & tuple) {
return IkarusEntityValue{tuple.template get<0>(), tuple.template get<1>()};
});
if (size_out) {
*size_out = values_plain.size();
@ -296,15 +363,19 @@ IkarusEntityValue * ikarus_entity_get_values(
return values;
}
char const * ikarus_entity_get_value(
IkarusEntity * entity,
char const * name,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
char const * ikarus_entity_get_value(IkarusEntity * entity, char const * name, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(name, nullptr);
IKARUS_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_ASCERTAIN(
nullptr,
"entity doesn't have value",
IkarusErrorInfo_Client_NotLinked,
ikarus_entity_has_value,
entity,
name
);
IKARUS_VTRYRV_OR_FAIL(
auto value,
nullptr,
@ -326,10 +397,16 @@ void ikarus_entity_set_value(
char const * value,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NULL(name, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NULL(value, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NAME_INVALID(name, IKARUS_VOID_RETURN);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
// parsing from & to here to ensure values are valid JSON & formatted
// uniformly
@ -338,7 +415,7 @@ void ikarus_entity_set_value(
IKARUS_VOID_RETURN,
"cannot parse value as JSON: {}",
IkarusErrorInfo_Client_InvalidInput,
IkarusValue::from_json(value)
IkarusValue::from_json_str(value)
);
IKARUS_TRYRV_OR_FAIL(
@ -361,29 +438,64 @@ void ikarus_entity_delete_value(
IkarusEntityDeleteValueFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NULL(name, IKARUS_VOID_RETURN);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_TRYRV_OR_FAIL(
IKARUS_VOID_RETURN,
"failed to delete value for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->execute(
"DELETE FROM `entity_values` WHERE `entity` = ? AND `name` = ?",
entity->id,
name
)
entity->project->db->execute("DELETE FROM `entity_values` WHERE `entity` = ? AND `name` = ?", entity->id, name)
);
}
IkarusEntityPropertyValue * ikarus_entity_get_property_values(
bool ikarus_entity_has_property_value(
IkarusEntity * entity,
size_t * size_out,
struct IkarusProperty * property,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_ASCERTAIN(
false,
"property doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_property_exists,
property
);
IKARUS_FAIL_IF(
entity->project != property->project,
false,
"property does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_VTRYRV_OR_FAIL(
auto exists,
false,
"failed to check if entity has property value: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<bool>(
"SELECT EXISTS(SELECT 1 FROM `entity_property_values` WHERE `entity` = ? AND `property` = ?)",
entity->id,
property->id
)
);
return exists;
}
IkarusEntityPropertyValue *
ikarus_entity_get_property_values(IkarusEntity * entity, size_t * size_out, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_VTRYRV_OR_FAIL(
auto values_plain,
@ -391,24 +503,20 @@ IkarusEntityPropertyValue * ikarus_entity_get_property_values(
"failed to get property values for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_many<int64_t, char const *>(
"SELECT `property`, `value` FROM `entity_property_values` WHERE `entity` = ?",
"SELECT `e`.`property`, IFNULL(`e`.`value`, ikarus_default_value(`p`.`schema`)) FROM `entity_property_values` AS `e` "
"INNER JOIN `properties` AS `p` ON `p`.`id` = `e`.`property` "
" WHERE `e`.`entity` = ?",
entity->id
)
);
IkarusEntityPropertyValue * values =
new IkarusEntityPropertyValue[values_plain.size()];
std::transform(
std::cbegin(values_plain),
std::cend(values_plain),
values,
[entity](auto const & tuple) {
return IkarusEntityPropertyValue{
new IkarusProperty{entity->project, tuple.template get<0>()},
tuple.template get<1>()
};
}
);
IkarusEntityPropertyValue * values = new IkarusEntityPropertyValue[values_plain.size()];
std::transform(std::cbegin(values_plain), std::cend(values_plain), values, [entity](auto const & tuple) {
return IkarusEntityPropertyValue{
new IkarusProperty{entity->project, tuple.template get<0>()},
tuple.template get<1>()
};
});
if (size_out) {
*size_out = values_plain.size();
@ -417,15 +525,23 @@ IkarusEntityPropertyValue * ikarus_entity_get_property_values(
return values;
}
char const * ikarus_entity_get_property_value(
IkarusEntity * entity,
struct IkarusProperty * property,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr);
IKARUS_FAIL_IF_NULL(property, nullptr);
IKARUS_FAIL_IF_NOT_EXIST(property, nullptr);
char const *
ikarus_entity_get_property_value(IkarusEntity * entity, struct IkarusProperty * property, IkarusErrorData * error_out) {
IKARUS_ASCERTAIN(false, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
IKARUS_ASCERTAIN(
false,
"property doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_property_exists,
property
);
IKARUS_FAIL_IF(
entity->project != property->project,
nullptr,
"property does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_VTRYRV_OR_FAIL(
auto value,
@ -433,7 +549,9 @@ char const * ikarus_entity_get_property_value(
"failed to get property value for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->query_one<char const *>(
"SELECT `value` FROM `entity_property_values` WHERE `entity` = ? AND `property` = ?",
"SELECT IFNULL(`e`.`value`, ikarus_default_value(`p`.`schema`)) FROM `entity_property_values` AS `e` "
"INNER JOIN `properties` AS `p` ON `p`.`id` = `e`.`property` "
"WHERE `e`.`entity` = ? AND `e`.`property` = ?",
entity->id,
property->id
)
@ -449,12 +567,38 @@ void ikarus_entity_set_property_value(
IkarusEntitySetPropertyValueFlags flags,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(entity, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NULL(property, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF_NOT_EXIST(property, IKARUS_VOID_RETURN);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"property doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_property_exists,
property
);
IKARUS_FAIL_IF_NULL(value, IKARUS_VOID_RETURN);
IKARUS_FAIL_IF(
entity->project != property->project,
IKARUS_VOID_RETURN,
"property does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity does not have property value",
IkarusErrorInfo_Client_NotLinked,
ikarus_entity_has_property_value,
entity,
property
);
// parsing from & to here to ensure values are valid JSON & formatted
// uniformly
IKARUS_VTRYRV_OR_FAIL(
@ -462,7 +606,7 @@ void ikarus_entity_set_property_value(
IKARUS_VOID_RETURN,
"cannot parse value as JSON: {}",
IkarusErrorInfo_Client_InvalidInput,
IkarusValue::from_json(value)
IkarusValue::from_json_str(value)
);
IKARUS_TRYRV_OR_FAIL(
@ -478,3 +622,51 @@ void ikarus_entity_set_property_value(
)
);
}
void ikarus_entity_clear_property_value(
IkarusEntity * entity,
struct IkarusProperty * property,
IkarusEntitySetPropertyValueFlags flags,
IkarusErrorData * error_out
) {
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_entity_exists,
entity
);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"property doesn't exist",
IkarusErrorInfo_Client_NonExistent,
ikarus_property_exists,
property
);
IKARUS_FAIL_IF(
entity->project != property->project,
IKARUS_VOID_RETURN,
"property does not belong to entity's project",
IkarusErrorInfo_Client_NotLinked
);
IKARUS_ASCERTAIN(
IKARUS_VOID_RETURN,
"entity doesn't have property",
IkarusErrorInfo_Client_NotLinked,
ikarus_entity_has_property_value,
entity,
property
);
IKARUS_TRYRV_OR_FAIL(
IKARUS_VOID_RETURN,
"failed to clear property value for entity: {}",
IkarusErrorInfo_Database_QueryFailed,
entity->project->db->execute(
"DELETE FROM `entity_property_values` WHERE `entity` = ? AND `property` = ?",
entity->id,
property->id
)
);
}