add blueprint & property implementation
Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
parent
bfac86b8a1
commit
8dff07f3fc
6 changed files with 772 additions and 43 deletions
|
|
@ -154,6 +154,22 @@ IKA_API void ikarus_blueprint_set_name(
|
||||||
struct IkarusErrorData * error_out
|
struct IkarusErrorData * error_out
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// \brief Gets whether a blueprint has a property.
|
||||||
|
/// \param blueprint The blueprint to check the property of.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \param property The property to check the existence of.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \pre \li Must be in the same project as the blueprint.
|
||||||
|
/// \param error_out \see errors.h
|
||||||
|
/// \return True if the blueprint has the property, false otherwise or if an error occurs.
|
||||||
|
IKA_API bool ikarus_blueprint_has_property(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
struct IkarusProperty * property,
|
||||||
|
struct IkarusErrorData * error_out
|
||||||
|
);
|
||||||
|
|
||||||
/// \brief Gets the properties of a blueprint.
|
/// \brief Gets the properties of a blueprint.
|
||||||
/// \param blueprint The blueprint to get the properties of.
|
/// \param blueprint The blueprint to get the properties of.
|
||||||
/// \pre \li Must not be null.
|
/// \pre \li Must not be null.
|
||||||
|
|
@ -161,7 +177,7 @@ IKA_API void ikarus_blueprint_set_name(
|
||||||
/// \param size_out An out parameter for the number of items in the returned array or undefined if an error occurs.
|
/// \param size_out An out parameter for the number of items in the returned array or undefined if an error occurs.
|
||||||
/// \param error_out \see errors.h
|
/// \param error_out \see errors.h
|
||||||
/// \return The properties of the blueprint or null if an error occurs.
|
/// \return The properties of the blueprint or null if an error occurs.
|
||||||
IKA_API struct IkarusBlueprint ** ikarus_blueprint_get_properties(
|
IKA_API struct IkarusProperty ** ikarus_blueprint_get_properties(
|
||||||
struct IkarusBlueprint * blueprint,
|
struct IkarusBlueprint * blueprint,
|
||||||
size_t * size_out,
|
size_t * size_out,
|
||||||
struct IkarusErrorData * error_out
|
struct IkarusErrorData * error_out
|
||||||
|
|
@ -176,15 +192,15 @@ IKA_API struct IkarusBlueprint ** ikarus_blueprint_get_properties(
|
||||||
IKA_API size_t
|
IKA_API size_t
|
||||||
ikarus_blueprint_get_properties_count(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out);
|
ikarus_blueprint_get_properties_count(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out);
|
||||||
|
|
||||||
/// \brief Gets all entities linked to a blueprint.
|
/// \brief Gets the linked entities of a blueprint.
|
||||||
/// \param blueprint The blueprint to get the entities of.
|
/// \param blueprint The blueprint to get the linked entities of.
|
||||||
/// \pre \li Must not be null.
|
/// \pre \li Must not be null.
|
||||||
/// \pre \li Must exist.
|
/// \pre \li Must exist.
|
||||||
/// \param size_out An out parameter for the number of items in the returned array or undefined if an error occurs.
|
/// \param size_out An out parameter for the number of items in the returned array or undefined if an error occurs.
|
||||||
/// \remark Ignore if null.
|
/// \remark Ignore if null.
|
||||||
/// \param error_out \see errors.h
|
/// \param error_out \see errors.h
|
||||||
/// \return The entities linked to the blueprint or null if an error occurs.
|
/// \return The linked entities of the blueprint or null if an error occurs.
|
||||||
IKA_API struct IkarusEntity ** ikarus_blueprint_get_entities(
|
IKA_API struct IkarusEntity ** ikarus_blueprint_get_linked_entities(
|
||||||
struct IkarusBlueprint * blueprint,
|
struct IkarusBlueprint * blueprint,
|
||||||
size_t * size_out,
|
size_t * size_out,
|
||||||
struct IkarusErrorData * error_out
|
struct IkarusErrorData * error_out
|
||||||
|
|
@ -197,7 +213,7 @@ IKA_API struct IkarusEntity ** ikarus_blueprint_get_entities(
|
||||||
/// \param error_out \see errors.h
|
/// \param error_out \see errors.h
|
||||||
/// \return The number of entities linked to the blueprint or 0 if an error occurs.
|
/// \return The number of entities linked to the blueprint or 0 if an error occurs.
|
||||||
IKA_API size_t
|
IKA_API size_t
|
||||||
ikarus_blueprint_get_entities_count(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out);
|
ikarus_blueprint_get_linked_entities_count(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out);
|
||||||
|
|
||||||
IKARUS_END_HEADER
|
IKARUS_END_HEADER
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,23 +53,47 @@ enum IkarusPropertyCreateFlags {
|
||||||
/// \param project The project to create the property in.
|
/// \param project The project to create the property in.
|
||||||
/// \pre \li Must not be null.
|
/// \pre \li Must not be null.
|
||||||
/// \pre \li Must exist.
|
/// \pre \li Must exist.
|
||||||
|
/// \param blueprint The blueprint to create the property for.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
/// \param name The name of the property.
|
/// \param name The name of the property.
|
||||||
/// \pre \li Must not be null.
|
/// \pre \li Must not be null.
|
||||||
/// \pre \li Must not be empty.
|
/// \pre \li Must not be empty.
|
||||||
/// \param schema The schema of the property.
|
/// \param schema The schema of the property.
|
||||||
/// \pre \li Must not be null.
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must be a valid JSON buffer for a IkarusValueSchema. \see schema.h
|
||||||
|
/// \param default_value The default value of the property.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must be a valid JSON buffer for an IkarusValueData. \see data.h
|
||||||
/// \param flags Flags for creating the property.
|
/// \param flags Flags for creating the property.
|
||||||
/// \param error_out \see errors.h
|
/// \param error_out \see errors.h
|
||||||
/// \return The created property or NULL if an error occurred.
|
/// \return The created property or NULL if an error occurred.
|
||||||
/// \remark Must only be deleted with #ikarus_property_delete.
|
/// \remark Must only be deleted with #ikarus_property_delete.
|
||||||
IKA_API IkarusProperty * ikarus_property_create(
|
IKA_API IkarusProperty * ikarus_property_create(
|
||||||
struct IkarusProject * project,
|
struct IkarusBlueprint * blueprint,
|
||||||
char const * name,
|
char const * name,
|
||||||
struct IkarusValueSchema * schema,
|
char const * schema,
|
||||||
|
char const * default_value,
|
||||||
IkarusPropertyCreateFlags flags,
|
IkarusPropertyCreateFlags flags,
|
||||||
IkarusErrorData * error_out
|
IkarusErrorData * error_out
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// \brief Flags for copying a property.
|
||||||
|
enum IkarusPropertyCopyFlags {
|
||||||
|
/// \brief No flags.
|
||||||
|
IkarusPropertyCopyFlags_None = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Copy a property.
|
||||||
|
/// \param property The property to copy.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \param flags Flags for copying the property.
|
||||||
|
/// \param error_out \see errors.h
|
||||||
|
/// \return The copied property or NULL if an error occurred.
|
||||||
|
IKA_API IkarusProperty *
|
||||||
|
ikarus_property_copy(IkarusProperty * property, IkarusPropertyCopyFlags flags, IkarusErrorData * error_out);
|
||||||
|
|
||||||
/// \brief Flags for deleting a property.
|
/// \brief Flags for deleting a property.
|
||||||
enum IkarusPropertyDeleteFlags {
|
enum IkarusPropertyDeleteFlags {
|
||||||
/// \brief No flags.
|
/// \brief No flags.
|
||||||
|
|
@ -101,15 +125,6 @@ IKA_API struct IkarusProject * ikarus_property_get_project(IkarusProperty * prop
|
||||||
/// \remark Ownership remains with libikarus.
|
/// \remark Ownership remains with libikarus.
|
||||||
IKA_API char const * ikarus_property_get_name(IkarusProperty * property, IkarusErrorData * error_out);
|
IKA_API char const * ikarus_property_get_name(IkarusProperty * property, IkarusErrorData * error_out);
|
||||||
|
|
||||||
/// \brief Get the schema of a property.
|
|
||||||
/// \param property The property to get the schema of.
|
|
||||||
/// \pre \li Must not be null.
|
|
||||||
/// \pre \li Must exist.
|
|
||||||
/// \param error_out \see errors.h
|
|
||||||
/// \return The schema of the property or null if an error occurred.
|
|
||||||
/// \remark Ownership remains with libikarus.
|
|
||||||
IKA_API struct IkarusValueSchema * ikarus_property_get_schema(IkarusProperty * property, IkarusErrorData * error_out);
|
|
||||||
|
|
||||||
/// \brief Flags for setting the name of a property.
|
/// \brief Flags for setting the name of a property.
|
||||||
enum IkarusPropertySetNameFlags {
|
enum IkarusPropertySetNameFlags {
|
||||||
/// \brief No flags.
|
/// \brief No flags.
|
||||||
|
|
@ -133,6 +148,78 @@ IKA_API void ikarus_property_set_name(
|
||||||
IkarusErrorData * error_out
|
IkarusErrorData * error_out
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// \brief Get the schema of a property.
|
||||||
|
/// \param property The property to get the schema of.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \param error_out \see errors.h
|
||||||
|
/// \return The schema of the property in JSON format or null if an error occurred. \see schema.h
|
||||||
|
IKA_API char const * ikarus_property_get_schema(IkarusProperty * property, IkarusErrorData * error_out);
|
||||||
|
|
||||||
|
/// \brief Flags for setting the schema of a property.
|
||||||
|
enum IkarusPropertySetSchemaFlags {
|
||||||
|
/// \brief No flags.
|
||||||
|
IkarusPropertySetSchemaFlags_None = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Set the schema of a property.
|
||||||
|
/// \details Setting the schema of a property will reset all existing values.
|
||||||
|
/// \param property The property to set the schema of.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \param schema The new schema of the property.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must be a valid JSON buffer for a IkarusValueSchema. \see schema.h
|
||||||
|
/// \param new_default_value The new default value of the property.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must be a valid JSON buffer for an IkarusValueData. \see data.h
|
||||||
|
/// \param flags Flags for setting the schema of the property.
|
||||||
|
/// \param error_out \see errors.h
|
||||||
|
IKA_API void ikarus_property_set_schema(
|
||||||
|
IkarusProperty * property,
|
||||||
|
char const * schema,
|
||||||
|
char const * new_default_value,
|
||||||
|
IkarusPropertySetSchemaFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
);
|
||||||
|
|
||||||
|
/// \brief Get the default value of a property.
|
||||||
|
/// \param property The property to get the default value of.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \param error_out \see errors.h
|
||||||
|
/// \return The default value data of the property in JSON format or null if an error occurred. \see data.h
|
||||||
|
IKA_API char const * ikarus_property_get_default_value(IkarusProperty * property, IkarusErrorData * error_out);
|
||||||
|
|
||||||
|
/// \details The default value must match the schema of the property.
|
||||||
|
|
||||||
|
/// \brief Flags for setting the default value of a property.
|
||||||
|
enum IkarusPropertySetDefaultValueFlags {
|
||||||
|
/// \brief No flags.
|
||||||
|
IkarusPropertySetDefaultValueFlags_None = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Flags for setting the default value of a property.
|
||||||
|
/// \param property The property to set the default value of.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must exist.
|
||||||
|
/// \param value The new default value of the property.
|
||||||
|
/// \pre \li Must not be null.
|
||||||
|
/// \pre \li Must be valid JSON \see data.h
|
||||||
|
/// \pre \li Must be valid according to the property's schema.
|
||||||
|
/// \param flags Flags for setting the default value of the property.
|
||||||
|
/// \param error_out \see errors.h
|
||||||
|
IKA_API void ikarus_property_set_default_value(
|
||||||
|
IkarusProperty * property,
|
||||||
|
char const * value,
|
||||||
|
IkarusPropertySetDefaultValueFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
);
|
||||||
|
|
||||||
|
/// \brief Gets all values for a property.
|
||||||
|
/// \param property The property to get the values of.
|
||||||
|
///
|
||||||
|
|
||||||
IKARUS_END_HEADER
|
IKARUS_END_HEADER
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,27 @@
|
||||||
#include <ikarus/errors.hpp>
|
#include <ikarus/errors.hpp>
|
||||||
#include <ikarus/objects/blueprint.hpp>
|
#include <ikarus/objects/blueprint.hpp>
|
||||||
#include <ikarus/objects/entity.h>
|
#include <ikarus/objects/entity.h>
|
||||||
|
#include <ikarus/objects/property.h>
|
||||||
#include <ikarus/persistence/project.hpp>
|
#include <ikarus/persistence/project.hpp>
|
||||||
|
|
||||||
IkarusBlueprint::IkarusBlueprint(struct IkarusProject * project, int64_t id):
|
IkarusBlueprint::IkarusBlueprint(struct IkarusProject * project, int64_t id):
|
||||||
project{project},
|
project{project},
|
||||||
id{id} {}
|
id{id} {}
|
||||||
|
|
||||||
|
bool ikarus_blueprint_exists(IkarusBlueprint * blueprint, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_FAIL_IF_NULL(blueprint, false);
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto exists,
|
||||||
|
false,
|
||||||
|
"failed to check whether blueprint exists: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db
|
||||||
|
->query_one<bool>("SELECT EXISTS(SELECT 1 FROM `blueprints` WHERE `id` = ?)", blueprint->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
IkarusBlueprint * ikarus_blueprint_create(
|
IkarusBlueprint * ikarus_blueprint_create(
|
||||||
struct IkarusProject * project,
|
struct IkarusProject * project,
|
||||||
char const * name,
|
char const * name,
|
||||||
|
|
@ -35,17 +50,14 @@ IkarusBlueprint * ikarus_blueprint_create_from_entity(
|
||||||
IkarusBlueprintCreateFromEntityFlags flags,
|
IkarusBlueprintCreateFromEntityFlags flags,
|
||||||
struct IkarusErrorData * error_out
|
struct IkarusErrorData * error_out
|
||||||
) {
|
) {
|
||||||
IKARUS_TRYRV_OR_FAIL(
|
|
||||||
nullptr,
|
|
||||||
"{}",
|
|
||||||
IkarusErrorInfo_Database_QueryFailed,
|
|
||||||
ikarus_libikarus_func_call_to_result(
|
|
||||||
error_out,
|
|
||||||
ikarus_must_return_true(ikarus_entity_exists, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent),
|
|
||||||
entity
|
|
||||||
)
|
|
||||||
);
|
|
||||||
IKARUS_FAIL_IF_NAME_INVALID(name, nullptr);
|
IKARUS_FAIL_IF_NAME_INVALID(name, nullptr);
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"entity must not be null",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput,
|
||||||
|
ikarus_entity_exists,
|
||||||
|
entity
|
||||||
|
);
|
||||||
|
|
||||||
IKARUS_VTRYRV_OR_FAIL(
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
auto id,
|
auto id,
|
||||||
|
|
@ -59,15 +71,308 @@ IkarusBlueprint * ikarus_blueprint_create_from_entity(
|
||||||
|
|
||||||
CPPBASE_TRY(entity->project->db->execute(
|
CPPBASE_TRY(entity->project->db->execute(
|
||||||
"INSERT INTO `properties`(`blueprint`, `name`, `schema`) "
|
"INSERT INTO `properties`(`blueprint`, `name`, `schema`) "
|
||||||
"SELECT ?, `name`, json_extract(`value`, '$.schema') FROM `entity_values` "
|
"SELECT ?, `name`, json_extract(`value`, '$.schema') AS `schema` FROM `entity_values` "
|
||||||
"WHERE `entity` = ?",
|
"WHERE `entity` = ?",
|
||||||
id,
|
id,
|
||||||
entity->id
|
entity->id
|
||||||
))
|
))
|
||||||
|
|
||||||
return cppbase::ok(entity->project->db->last_insert_rowid());
|
return cppbase::ok(id);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return new IkarusBlueprint{entity->project, id};
|
return new IkarusBlueprint{entity->project, id};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IkarusBlueprint * ikarus_blueprint_copy(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
IkarusBlueprintCopyFlags flags,
|
||||||
|
struct IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto id,
|
||||||
|
nullptr,
|
||||||
|
"failed to copy blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->transact(
|
||||||
|
[blueprint](auto * db) -> cppbase::Result<int64_t, sqlitecpp::TransactionError> {
|
||||||
|
CPPBASE_TRY(db->execute(
|
||||||
|
"INSERT INTO `blueprints`(`name`) "
|
||||||
|
"SELECT `name` FROM `blueprints` WHERE `id` = ?",
|
||||||
|
blueprint->id
|
||||||
|
));
|
||||||
|
|
||||||
|
auto const id = db->last_insert_rowid();
|
||||||
|
|
||||||
|
CPPBASE_TRY(blueprint->project->db->execute(
|
||||||
|
"INSERT INTO `properties`(`blueprint`, `name`, `schema`) "
|
||||||
|
"SELECT ?, `name`, `schema` FROM `properties` "
|
||||||
|
"WHERE `blueprint` = ?",
|
||||||
|
id,
|
||||||
|
blueprint->id
|
||||||
|
));
|
||||||
|
|
||||||
|
return cppbase::ok(id);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new IkarusBlueprint{blueprint->project, id};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ikarus_blueprint_delete(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
IkarusBlueprintDeleteFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"failed to delete blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->execute("DELETE FROM `blueprints` WHERE `id` = ?", blueprint->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
delete blueprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IkarusProject *
|
||||||
|
ikarus_blueprint_get_project(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
return blueprint->project;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * ikarus_blueprint_get_name(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto name,
|
||||||
|
nullptr,
|
||||||
|
"failed to get name for blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->query_one<char const *>("SELECT `name` FROM `blueprints` WHERE `id` = ?", blueprint->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ikarus_blueprint_set_name(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
char const * name,
|
||||||
|
IkarusBlueprintSetNameFlags flags,
|
||||||
|
struct IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
IKARUS_FAIL_IF_NAME_INVALID(name, IKARUS_VOID_RETURN);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"failed to set name for blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->execute("UPDATE `blueprints` SET `name` = ? WHERE `id` = ?", name, blueprint->id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ikarus_blueprint_has_property(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
struct IkarusProperty * property,
|
||||||
|
struct IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
false,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
false,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_FAIL_IF(
|
||||||
|
blueprint->project != property->project,
|
||||||
|
false,
|
||||||
|
"property does not belong to blueprint's project",
|
||||||
|
IkarusErrorInfo_Client_NotLinked
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto exists,
|
||||||
|
false,
|
||||||
|
"failed to check if blueprint has property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->query_one<bool>(
|
||||||
|
"SELECT EXISTS(SELECT 1 FROM `properties` WHERE `blueprint` = ? AND `id` = ?)",
|
||||||
|
blueprint->id,
|
||||||
|
property->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IkarusProperty ** ikarus_blueprint_get_properties(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
size_t * size_out,
|
||||||
|
struct IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VCALL(auto count, nullptr, ikarus_blueprint_get_properties_count, blueprint);
|
||||||
|
|
||||||
|
std::int64_t ids[count];
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
nullptr,
|
||||||
|
"failed to get properties for blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->query_many_buffered<std::int64_t>(
|
||||||
|
"SELECT `id` FROM `properties` WHERE `blueprint` = ?",
|
||||||
|
ids,
|
||||||
|
count,
|
||||||
|
blueprint->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto properties = new IkarusProperty *[count];
|
||||||
|
std::transform(ids, ids + count, properties, [project = blueprint->project](auto id) {
|
||||||
|
return new IkarusProperty{project, id};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (size_out) {
|
||||||
|
*size_out = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ikarus_blueprint_get_properties_count(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
0,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto count,
|
||||||
|
0,
|
||||||
|
"failed to get properties count for blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db
|
||||||
|
->query_one<std::int64_t>("SELECT COUNT(*) FROM `properties` WHERE `blueprint` = ?", blueprint->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IkarusEntity ** ikarus_blueprint_get_linked_entities(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
size_t * size_out,
|
||||||
|
struct IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VCALL(auto count, nullptr, ikarus_blueprint_get_linked_entities_count, blueprint);
|
||||||
|
|
||||||
|
std::int64_t ids[count];
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
nullptr,
|
||||||
|
"failed to get entities for blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->query_many_buffered<std::int64_t>(
|
||||||
|
"SELECT `entity` FROM `entity_blueprint_links` WHERE `blueprint` = ?",
|
||||||
|
ids,
|
||||||
|
count,
|
||||||
|
blueprint->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto entities = new IkarusEntity *[count];
|
||||||
|
std::transform(ids, ids + count, entities, [project = blueprint->project](auto id) {
|
||||||
|
return new IkarusEntity{project, id};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (size_out) {
|
||||||
|
*size_out = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ikarus_blueprint_get_linked_entities_count(struct IkarusBlueprint * blueprint, struct IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
0,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto count,
|
||||||
|
0,
|
||||||
|
"failed to get linked entities count for blueprint: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->query_one<std::int64_t>(
|
||||||
|
"SELECT COUNT(*) FROM `entity_blueprint_links` WHERE `blueprint` = ?",
|
||||||
|
blueprint->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ IkarusEntity * ikarus_entity_copy(IkarusEntity * entity, IkarusEntityCopyFlags f
|
||||||
entity->id
|
entity->id
|
||||||
));
|
));
|
||||||
|
|
||||||
|
auto const id = entity->project->db->last_insert_rowid();
|
||||||
|
|
||||||
CPPBASE_TRY(entity->project->db->execute(
|
CPPBASE_TRY(entity->project->db->execute(
|
||||||
"INSERT INTO `entity_values`(`entity`, `name`, `value`) "
|
"INSERT INTO `entity_values`(`entity`, `name`, `value`) "
|
||||||
"SELECT ?1, `name`, `value` FROM `entity_values` WHERE "
|
"SELECT ?1, `name`, `value` FROM `entity_values` WHERE "
|
||||||
|
|
@ -101,7 +103,7 @@ IkarusEntity * ikarus_entity_copy(IkarusEntity * entity, IkarusEntityCopyFlags f
|
||||||
entity->id
|
entity->id
|
||||||
))
|
))
|
||||||
|
|
||||||
return cppbase::ok(entity->project->db->last_insert_rowid());
|
return cppbase::ok(id);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -189,8 +191,8 @@ bool ikarus_entity_is_linked_to_blueprint(
|
||||||
|
|
||||||
struct IkarusBlueprint **
|
struct IkarusBlueprint **
|
||||||
ikarus_entity_get_linked_blueprints(IkarusEntity * entity, size_t * size_out, IkarusErrorData * error_out) {
|
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_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
|
||||||
IKARUS_VCALL(auto count, false, ikarus_entity_get_linked_blueprints_count, entity);
|
IKARUS_VCALL(auto count, nullptr, ikarus_entity_get_linked_blueprints_count, entity);
|
||||||
|
|
||||||
std::int64_t ids[count];
|
std::int64_t ids[count];
|
||||||
|
|
||||||
|
|
@ -495,7 +497,7 @@ bool ikarus_entity_has_property_value(
|
||||||
|
|
||||||
IkarusEntityPropertyValue *
|
IkarusEntityPropertyValue *
|
||||||
ikarus_entity_get_property_values(IkarusEntity * entity, size_t * size_out, IkarusErrorData * error_out) {
|
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_ASCERTAIN(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
|
||||||
|
|
||||||
IKARUS_VTRYRV_OR_FAIL(
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
auto values_plain,
|
auto values_plain,
|
||||||
|
|
@ -503,9 +505,12 @@ ikarus_entity_get_property_values(IkarusEntity * entity, size_t * size_out, Ikar
|
||||||
"failed to get property values for entity: {}",
|
"failed to get property values for entity: {}",
|
||||||
IkarusErrorInfo_Database_QueryFailed,
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
entity->project->db->query_many<int64_t, char const *>(
|
entity->project->db->query_many<int64_t, char const *>(
|
||||||
"SELECT `e`.`property`, IFNULL(`e`.`value`, ikarus_default_value(`p`.`schema`)) FROM `entity_property_values` AS `e` "
|
"SELECT `p`.`id`, IFNULL(`v`.`value`, ikarus_default_value(`p`.`schema`)) "
|
||||||
"INNER JOIN `properties` AS `p` ON `p`.`id` = `e`.`property` "
|
"FROM `entities` AS `e` "
|
||||||
" WHERE `e`.`entity` = ?",
|
"INNER JOIN `entity_blueprint_links` as `l` ON `l`.`entity` = `e`.`id` "
|
||||||
|
"INNER JOIN `properties` AS `p` ON `p`.`blueprint` = `l`.`blueprint` "
|
||||||
|
"LEFT JOIN `entity_property_values` AS `v` ON `e`.`entity` = `e`.`id` "
|
||||||
|
"WHERE `e`.`entity` = ?",
|
||||||
entity->id
|
entity->id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
@ -527,9 +532,9 @@ ikarus_entity_get_property_values(IkarusEntity * entity, size_t * size_out, Ikar
|
||||||
|
|
||||||
char const *
|
char const *
|
||||||
ikarus_entity_get_property_value(IkarusEntity * entity, struct IkarusProperty * property, IkarusErrorData * error_out) {
|
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(nullptr, "entity doesn't exist", IkarusErrorInfo_Client_NonExistent, ikarus_entity_exists, entity);
|
||||||
IKARUS_ASCERTAIN(
|
IKARUS_ASCERTAIN(
|
||||||
false,
|
nullptr,
|
||||||
"property doesn't exist",
|
"property doesn't exist",
|
||||||
IkarusErrorInfo_Client_NonExistent,
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
ikarus_property_exists,
|
ikarus_property_exists,
|
||||||
|
|
@ -543,6 +548,15 @@ ikarus_entity_get_property_value(IkarusEntity * entity, struct IkarusProperty *
|
||||||
IkarusErrorInfo_Client_NotLinked
|
IkarusErrorInfo_Client_NotLinked
|
||||||
);
|
);
|
||||||
|
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"entity doesn't have property value",
|
||||||
|
IkarusErrorInfo_Client_NotLinked,
|
||||||
|
ikarus_entity_has_property_value,
|
||||||
|
entity,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
IKARUS_VTRYRV_OR_FAIL(
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
auto value,
|
auto value,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
|
@ -567,6 +581,8 @@ void ikarus_entity_set_property_value(
|
||||||
IkarusEntitySetPropertyValueFlags flags,
|
IkarusEntitySetPropertyValueFlags flags,
|
||||||
IkarusErrorData * error_out
|
IkarusErrorData * error_out
|
||||||
) {
|
) {
|
||||||
|
IKARUS_FAIL_IF_NULL(value, IKARUS_VOID_RETURN);
|
||||||
|
|
||||||
IKARUS_ASCERTAIN(
|
IKARUS_ASCERTAIN(
|
||||||
IKARUS_VOID_RETURN,
|
IKARUS_VOID_RETURN,
|
||||||
"entity doesn't exist",
|
"entity doesn't exist",
|
||||||
|
|
@ -581,7 +597,6 @@ void ikarus_entity_set_property_value(
|
||||||
ikarus_property_exists,
|
ikarus_property_exists,
|
||||||
property
|
property
|
||||||
);
|
);
|
||||||
IKARUS_FAIL_IF_NULL(value, IKARUS_VOID_RETURN);
|
|
||||||
|
|
||||||
IKARUS_FAIL_IF(
|
IKARUS_FAIL_IF(
|
||||||
entity->project != property->project,
|
entity->project != property->project,
|
||||||
|
|
@ -650,6 +665,7 @@ void ikarus_entity_clear_property_value(
|
||||||
"property does not belong to entity's project",
|
"property does not belong to entity's project",
|
||||||
IkarusErrorInfo_Client_NotLinked
|
IkarusErrorInfo_Client_NotLinked
|
||||||
);
|
);
|
||||||
|
|
||||||
IKARUS_ASCERTAIN(
|
IKARUS_ASCERTAIN(
|
||||||
IKARUS_VOID_RETURN,
|
IKARUS_VOID_RETURN,
|
||||||
"entity doesn't have property",
|
"entity doesn't have property",
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,316 @@
|
||||||
|
|
||||||
#include <ikarus/errors.h>
|
#include <ikarus/errors.h>
|
||||||
#include <ikarus/errors.hpp>
|
#include <ikarus/errors.hpp>
|
||||||
|
#include <ikarus/objects/blueprint.h>
|
||||||
#include <ikarus/objects/property.h>
|
#include <ikarus/objects/property.h>
|
||||||
#include <ikarus/persistence/project.hpp>
|
#include <ikarus/persistence/project.hpp>
|
||||||
|
|
||||||
IkarusProperty::IkarusProperty(struct IkarusProject * project, int64_t id):
|
IkarusProperty::IkarusProperty(struct IkarusProject * project, int64_t id):
|
||||||
project{project},
|
project{project},
|
||||||
id{id} {}
|
id{id} {}
|
||||||
|
|
||||||
|
bool ikarus_property_exists(IkarusProperty * property, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_FAIL_IF_NULL(property, false);
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto exists,
|
||||||
|
false,
|
||||||
|
"failed to check whether property exists: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->query_one<bool>("SELECT EXISTS(SELECT 1 FROM `properties` WHERE `id` = ?)", property->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
IkarusProperty * ikarus_property_create(
|
||||||
|
struct IkarusBlueprint * blueprint,
|
||||||
|
char const * name,
|
||||||
|
char const * schema,
|
||||||
|
char const * default_value,
|
||||||
|
IkarusPropertyCreateFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_FAIL_IF_NULL(blueprint, nullptr);
|
||||||
|
IKARUS_FAIL_IF_NAME_INVALID(name, nullptr);
|
||||||
|
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"blueprint doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_blueprint_exists,
|
||||||
|
blueprint
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto schema_parsed,
|
||||||
|
nullptr,
|
||||||
|
"cannot parse schema as JSON: {}",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput,
|
||||||
|
IkarusValueSchema::from_json_str(schema)
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto default_value_parsed,
|
||||||
|
nullptr,
|
||||||
|
"cannot parse default value as JSON: {}",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput,
|
||||||
|
IkarusValueData::from_json_str(default_value)
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_FAIL_IF(
|
||||||
|
!schema_parsed.validate(default_value_parsed),
|
||||||
|
nullptr,
|
||||||
|
"default value is invalid for schema",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
nullptr,
|
||||||
|
"failed to create property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
blueprint->project->db->execute(
|
||||||
|
"INSERT INTO `properties`(`blueprint`, `name`, `schema`, `default_value`) VALUES(?, ?, ?, ?)",
|
||||||
|
blueprint->id,
|
||||||
|
name,
|
||||||
|
IkarusValueSchema::to_json(schema_parsed).dump(),
|
||||||
|
IkarusValueData::to_json(default_value_parsed).dump()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto const id = blueprint->project->db->last_insert_rowid();
|
||||||
|
return new IkarusProperty{blueprint->project, id};
|
||||||
|
}
|
||||||
|
|
||||||
|
IkarusProperty *
|
||||||
|
ikarus_property_copy(IkarusProperty * property, IkarusPropertyCopyFlags flags, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
nullptr,
|
||||||
|
"failed to copy property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->execute(
|
||||||
|
"INSERT INTO `properties`(`blueprint`, `name`, `schema`, `default_value`) "
|
||||||
|
"SELECT `blueprint`, `name`, `schema`, `default_value` FROM `properties` WHERE `id` = ?",
|
||||||
|
property->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto const id = property->project->db->last_insert_rowid();
|
||||||
|
return new IkarusProperty{property->project, id};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ikarus_property_delete(IkarusProperty * property, IkarusPropertyDeleteFlags flags, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"failed to delete property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->execute("DELETE FROM `properties` WHERE `id` = ?", property->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
delete property;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IkarusProject * ikarus_property_get_project(IkarusProperty * property, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
return property->project;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * ikarus_property_get_name(IkarusProperty * property, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto name,
|
||||||
|
nullptr,
|
||||||
|
"failed to get name for property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->query_one<char const *>("SELECT `name` FROM `properties` WHERE `id` = ?", property->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ikarus_property_set_name(
|
||||||
|
IkarusProperty * property,
|
||||||
|
char const * name,
|
||||||
|
IkarusPropertySetNameFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_FAIL_IF_NULL(name, IKARUS_VOID_RETURN);
|
||||||
|
IKARUS_FAIL_IF_NAME_INVALID(name, IKARUS_VOID_RETURN);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"failed to set name for property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->execute("UPDATE `properties` SET `name` = ? WHERE `id` = ?", name, property->id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * ikarus_property_get_schema(IkarusProperty * property, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto schema,
|
||||||
|
nullptr,
|
||||||
|
"failed to get schema for property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->query_one<char const *>("SELECT `schema` FROM `properties` WHERE `id` = ?", property->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ikarus_property_set_schema(
|
||||||
|
IkarusProperty * property,
|
||||||
|
char const * schema,
|
||||||
|
char const * new_default_value,
|
||||||
|
IkarusPropertySetSchemaFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_FAIL_IF_NULL(schema, IKARUS_VOID_RETURN);
|
||||||
|
IKARUS_FAIL_IF_NULL(new_default_value, IKARUS_VOID_RETURN);
|
||||||
|
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto schema_parsed,
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"cannot parse schema as JSON: {}",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput,
|
||||||
|
IkarusValueSchema::from_json_str(schema)
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto default_value_parsed,
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"cannot parse default value as JSON: {}",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput,
|
||||||
|
IkarusValueData::from_json_str(new_default_value)
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_FAIL_IF(
|
||||||
|
!schema_parsed.validate(default_value_parsed),
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"default value is invalid for schema",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput
|
||||||
|
);
|
||||||
|
|
||||||
|
// transact updating the property and all of its associated values
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"failed to set schema for property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->transact([&](auto * db) -> cppbase::Result<void, sqlitecpp::TransactionError> {
|
||||||
|
CPPBASE_TRY(db->execute(
|
||||||
|
"UPDATE `properties` SET `schema` = ? WHERE `id` = ?",
|
||||||
|
IkarusValueSchema::to_json(schema_parsed).dump(),
|
||||||
|
property->id
|
||||||
|
));
|
||||||
|
|
||||||
|
CPPBASE_TRY(db->execute(
|
||||||
|
"UPDATE `entity_property_values` SET `value` = ? WHERE `property` = ?",
|
||||||
|
IkarusValueData::to_json(default_value_parsed).dump(),
|
||||||
|
property->id
|
||||||
|
));
|
||||||
|
|
||||||
|
return cppbase::ok();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * ikarus_property_get_default_value(IkarusProperty * property, IkarusErrorData * error_out) {
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
nullptr,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto default_value,
|
||||||
|
nullptr,
|
||||||
|
"failed to get default value for property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db
|
||||||
|
->query_one<char const *>("SELECT `default_value` FROM `properties` WHERE `id` = ?", property->id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ikarus_property_set_default_value(
|
||||||
|
IkarusProperty * property,
|
||||||
|
char const * value,
|
||||||
|
IkarusPropertySetDefaultValueFlags flags,
|
||||||
|
IkarusErrorData * error_out
|
||||||
|
) {
|
||||||
|
IKARUS_FAIL_IF_NULL(value, IKARUS_VOID_RETURN);
|
||||||
|
|
||||||
|
IKARUS_ASCERTAIN(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"property doesn't exist",
|
||||||
|
IkarusErrorInfo_Client_NonExistent,
|
||||||
|
ikarus_property_exists,
|
||||||
|
property
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_VTRYRV_OR_FAIL(
|
||||||
|
auto value_parsed,
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"cannot parse value as JSON: {}",
|
||||||
|
IkarusErrorInfo_Client_InvalidInput,
|
||||||
|
IkarusValueData::from_json_str(value)
|
||||||
|
);
|
||||||
|
|
||||||
|
IKARUS_TRYRV_OR_FAIL(
|
||||||
|
IKARUS_VOID_RETURN,
|
||||||
|
"failed to set default value for property: {}",
|
||||||
|
IkarusErrorInfo_Database_QueryFailed,
|
||||||
|
property->project->db->execute(
|
||||||
|
"UPDATE `properties` SET `default_value` = ? WHERE `id` = ?",
|
||||||
|
IkarusValueData::to_json(value_parsed).dump(),
|
||||||
|
property->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ CREATE TABLE `entity_values`
|
||||||
`name` TEXT NOT NULL,
|
`name` TEXT NOT NULL,
|
||||||
`value` TEXT NOT NULL,
|
`value` TEXT NOT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`entity`, `name`)
|
||||||
UNIQUE (`entity`, `name`)
|
|
||||||
) STRICT;
|
) STRICT;
|
||||||
|
|
||||||
CREATE TABLE `blueprints`
|
CREATE TABLE `blueprints`
|
||||||
|
|
@ -44,6 +43,5 @@ CREATE TABLE `entity_property_values`
|
||||||
`property` INTEGER NOT NULL REFERENCES `properties` (`id`) ON DELETE CASCADE,
|
`property` INTEGER NOT NULL REFERENCES `properties` (`id`) ON DELETE CASCADE,
|
||||||
`value` TEXT NOT NULL,
|
`value` TEXT NOT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`entity`, `property`)
|
||||||
UNIQUE (`entity`, `property`)
|
|
||||||
) STRICT;
|
) STRICT;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue