Skip to content
Snippets Groups Projects
Verified Commit e1e12e85 authored by Timm Fitschen's avatar Timm Fitschen
Browse files

WIP: update entity

parent 6ebcedc8
No related branches found
No related tags found
1 merge request!6F update
Pipeline #11091 passed
Pipeline: caosdb-cppinttest

#11098

    This commit is part of merge request !6. Comments created here will be created in the context of that merge request.
    ...@@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools ...@@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools
    class CaosdbConan(ConanFile): class CaosdbConan(ConanFile):
    name = "caosdb" name = "caosdb"
    version = "0.0.8" version = "0.0.9"
    license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"
    author = "Timm C. Fitschen <t.fitschen@indiscale.com>" author = "Timm C. Fitschen <t.fitschen@indiscale.com>"
    url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git" url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git"
    ......
    ...@@ -278,6 +278,9 @@ private: ...@@ -278,6 +278,9 @@ private:
    class Entity { class Entity {
    public: public:
    Entity(); Entity();
    inline Entity(const Entity &original) : Entity(CreateProtoEntity()) {
    this->wrapped->CopyFrom(*original.wrapped);
    };
    explicit Entity(IdResponse *idResponse); explicit Entity(IdResponse *idResponse);
    explicit inline Entity(ProtoEntity *wrapped) : wrapped(wrapped) { explicit inline Entity(ProtoEntity *wrapped) : wrapped(wrapped) {
    errors.wrapped = this->wrapped->mutable_errors(); errors.wrapped = this->wrapped->mutable_errors();
    ...@@ -287,9 +290,12 @@ public: ...@@ -287,9 +290,12 @@ public:
    parents.wrapped = this->wrapped->mutable_parents(); parents.wrapped = this->wrapped->mutable_parents();
    }; };
    [[nodiscard]] inline auto GetId() const -> const std::string & { [[nodiscard]] inline auto GetId() const noexcept -> const std::string & {
    return wrapped->id(); return wrapped->id();
    }; };
    [[nodiscard]] inline auto HasId() const noexcept -> bool {
    return !wrapped->id().empty();
    }
    [[nodiscard]] inline auto GetVersionId() const -> const std::string & { [[nodiscard]] inline auto GetVersionId() const -> const std::string & {
    return wrapped->version().id(); return wrapped->version().id();
    }; };
    ...@@ -333,9 +339,7 @@ public: ...@@ -333,9 +339,7 @@ public:
    } }
    auto SetRole(const std::string &role) -> void; auto SetRole(const std::string &role) -> void;
    auto SetId(const std::string &id) -> void;
    auto SetName(const std::string &name) -> void; auto SetName(const std::string &name) -> void;
    auto SetVersionId(const std::string &id) -> void;
    // TODO(fspreck) ... and also these // TODO(fspreck) ... and also these
    auto SetValue(const std::string &value) -> void; auto SetValue(const std::string &value) -> void;
    ...@@ -348,8 +352,12 @@ public: ...@@ -348,8 +352,12 @@ public:
    auto AppendParent(const Parent &parent) -> void; auto AppendParent(const Parent &parent) -> void;
    auto Switch(ProtoEntity *entity) -> void; auto Switch(ProtoEntity *entity) -> void;
    private: protected:
    static auto CreateProtoEntity() -> ProtoEntity *; static auto CreateProtoEntity() -> ProtoEntity *;
    auto SetId(const std::string &id) -> void;
    auto SetVersionId(const std::string &id) -> void;
    private:
    ProtoEntity *wrapped; ProtoEntity *wrapped;
    Properties properties; Properties properties;
    Parents parents; Parents parents;
    ......
    ...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
    namespace caosdb { namespace caosdb {
    enum StatusCode { enum StatusCode {
    READY = -4,
    GO_ON = -3,
    INITIAL = -2, INITIAL = -2,
    EXECUTING = -1, EXECUTING = -1,
    SUCCESS = 0, SUCCESS = 0,
    ...@@ -48,6 +50,7 @@ enum StatusCode { ...@@ -48,6 +50,7 @@ enum StatusCode {
    TRANSACTION_STATUS_ERROR = 25, TRANSACTION_STATUS_ERROR = 25,
    TRANSACTION_TYPE_ERROR = 26, TRANSACTION_TYPE_ERROR = 26,
    UNSUPPORTED_FEATURE = 27, UNSUPPORTED_FEATURE = 27,
    ORIGINAL_ENTITY_MISSING_ID = 28,
    }; };
    auto get_status_description(int code) -> const std::string &; auto get_status_description(int code) -> const std::string &;
    ......
    ...@@ -106,6 +106,35 @@ ...@@ -106,6 +106,35 @@
    "wrong TransactionType.") \ "wrong TransactionType.") \
    } }
    /*
    * Do all necessary checks and assure that another update can be added as a
    * sub-request to a transaction.
    */
    #define ASSERT_CAN_ADD_UPDATE \
    if (!IsStatus(TransactionStatus::INITIAL())) { \
    return StatusCode::TRANSACTION_STATUS_ERROR; \
    } \
    switch (this->transaction_type) { \
    case NONE: \
    this->transaction_type = TransactionType::INSERT; \
    case INSERT: \
    case MIXED_WRITE: \
    case MIXED_READ_AND_WRITE: \
    break; \
    default: \
    CAOSDB_LOG_ERROR_AND_RETURN_STATUS( \
    logger_name, StatusCode::TRANSACTION_TYPE_ERROR, \
    "You cannot add an update to this transaction because it has the " \
    "wrong TransactionType.") \
    } \
    if (!entity->HasId()) { \
    CAOSDB_LOG_ERROR_AND_RETURN_STATUS( \
    logger_name, StatusCode::ORIGINAL_ENTITY_MISSING_ID, \
    "You cannot update this entity without any id. Probably you did not " \
    "retrieve it first? Entity updates should always start with the " \
    "retrieval of the existing entity which may then be changed.") \
    }
    namespace caosdb::transaction { namespace caosdb::transaction {
    using caosdb::entity::Entity; using caosdb::entity::Entity;
    using ProtoEntity = caosdb::entity::v1alpha1::Entity; using ProtoEntity = caosdb::entity::v1alpha1::Entity;
    ...@@ -233,6 +262,16 @@ public: ...@@ -233,6 +262,16 @@ public:
    */ */
    auto InsertEntity(Entity *entity) noexcept -> StatusCode; auto InsertEntity(Entity *entity) noexcept -> StatusCode;
    /**
    * Add the entity to this transaction for an update.
    *
    * The update is being processed when the Execute() or
    * ExecuteAsynchronously() methods of this transaction are called.
    *
    * Changing the entity afterwards results in undefined behavior.
    */
    auto UpdateEntity(Entity *entity) noexcept -> StatusCode;
    /** /**
    * Add an entity id to this transaction for deletion. * Add an entity id to this transaction for deletion.
    * *
    ......
    ...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
    #include "caosdb/utility.h" // for get_home_direc... #include "caosdb/utility.h" // for get_home_direc...
    #include <cassert> // for assert #include <cassert> // for assert
    #include <cstdlib> // for getenv #include <cstdlib> // for getenv
    #include <cstring> // IWYU pragma: keep
    #include <exception> // IWYU pragma: keep #include <exception> // IWYU pragma: keep
    #include <grpcpp/security/credentials.h> // for SslCredentials #include <grpcpp/security/credentials.h> // for SslCredentials
    #include <iterator> // for next #include <iterator> // for next
    ......
    ...@@ -42,8 +42,14 @@ namespace caosdb { ...@@ -42,8 +42,14 @@ namespace caosdb {
    auto get_status_description(int code) -> const std::string & { auto get_status_description(int code) -> const std::string & {
    static const std::string MISSING_DESCRIPTION = "MISSING DESCRIPTION"; static const std::string MISSING_DESCRIPTION = "MISSING DESCRIPTION";
    static const std::map<int, std::string> descriptions = { static const std::map<int, std::string> descriptions = {
    {StatusCode::INITIAL, "The transaction has not been executed yet and " {StatusCode::INITIAL,
    "clients can stil change it."}, "The transaction has just been intialized. It has not been executed yet "
    "and clients can still change it and add sub-transactions."},
    {StatusCode::GO_ON,
    "The transaction has a transaction_type yet and clients may add matching "
    "sub-transaction or execute it right-away."},
    {StatusCode::READY,
    "The transaction is ready for execution and cannot be changed anymore."},
    {StatusCode::EXECUTING, "The transaction is currently being executed."}, {StatusCode::EXECUTING, "The transaction is currently being executed."},
    {StatusCode::SUCCESS, "The action was successful"}, {StatusCode::SUCCESS, "The action was successful"},
    {StatusCode::CONNECTION_ERROR, {StatusCode::CONNECTION_ERROR,
    ...@@ -68,6 +74,10 @@ auto get_status_description(int code) -> const std::string & { ...@@ -68,6 +74,10 @@ auto get_status_description(int code) -> const std::string & {
    {StatusCode::TRANSACTION_TYPE_ERROR, {StatusCode::TRANSACTION_TYPE_ERROR,
    "The Transaction has a transaction type which does not allow the " "The Transaction has a transaction type which does not allow the "
    "attempted action."}, "attempted action."},
    {StatusCode::ORIGINAL_ENTITY_MISSING_ID,
    "The attempt to update this entity failed because this entity does have "
    "an id. This is the case when you did not retrieve it before applying any "
    "changes and instantiated the Entity class explicitely."},
    {StatusCode::UNSUPPORTED_FEATURE, {StatusCode::UNSUPPORTED_FEATURE,
    "This feature is not available in the this client implementation."}}; "This feature is not available in the this client implementation."}};
    try { try {
    ...@@ -142,6 +152,17 @@ auto Transaction::InsertEntity(Entity *entity) noexcept -> StatusCode { ...@@ -142,6 +152,17 @@ auto Transaction::InsertEntity(Entity *entity) noexcept -> StatusCode {
    return StatusCode::INITIAL; return StatusCode::INITIAL;
    } }
    auto Transaction::UpdateEntity(Entity *entity) noexcept -> StatusCode {
    ASSERT_CAN_ADD_UPDATE
    auto *sub_request = this->request->add_requests();
    auto *proto_entity = sub_request->mutable_update_request();
    entity->Switch(proto_entity);
    return StatusCode::INITIAL;
    }
    auto Transaction::Execute() -> TransactionStatus { auto Transaction::Execute() -> TransactionStatus {
    ExecuteAsynchronously(); ExecuteAsynchronously();
    this->status.ThrowExceptionIfError(); this->status.ThrowExceptionIfError();
    ...@@ -221,6 +242,14 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { ...@@ -221,6 +242,14 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus {
    } }
    this->result_set = std::make_unique<UniqueResult>(entity); this->result_set = std::make_unique<UniqueResult>(entity);
    } break; } break;
    case WrappedResponseCase::kUpdateResponse: {
    auto *updatedIdResponse = responses->mutable_update_response();
    if (!updatedIdResponse->entity_errors().empty()) {
    this->status = TransactionStatus::TRANSACTION_ERROR(
    "The request returned with errors.");
    }
    this->result_set = std::make_unique<UniqueResult>(updatedIdResponse);
    } break;
    case WrappedResponseCase::kInsertResponse: { case WrappedResponseCase::kInsertResponse: {
    auto *insertedIdResponse = responses->mutable_insert_response(); auto *insertedIdResponse = responses->mutable_insert_response();
    if (!insertedIdResponse->entity_errors().empty()) { if (!insertedIdResponse->entity_errors().empty()) {
    ......
    ...@@ -61,16 +61,16 @@ TEST(test_entity, test_insert_entity) { ...@@ -61,16 +61,16 @@ TEST(test_entity, test_insert_entity) {
    std::shared_ptr<transaction::EntityTransactionService::Stub>(nullptr)); std::shared_ptr<transaction::EntityTransactionService::Stub>(nullptr));
    auto entity = Entity(); auto entity = Entity();
    entity.SetId("entity_id"); entity.SetRole("entity_role");
    entity.SetVersionId("version_id"); entity.SetName("entity_name");
    EXPECT_EQ(entity.GetId(), "entity_id"); EXPECT_EQ(entity.GetRole(), "entity_role");
    EXPECT_EQ(entity.GetVersionId(), "version_id"); EXPECT_EQ(entity.GetName(), "entity_name");
    transaction.InsertEntity(&entity); transaction.InsertEntity(&entity);
    EXPECT_EQ(entity.GetId(), "entity_id"); EXPECT_EQ(entity.GetRole(), "entity_role");
    EXPECT_EQ(entity.GetVersionId(), "version_id"); EXPECT_EQ(entity.GetName(), "entity_name");
    } }
    // TODO(tf) cognitive complexity > 25 (threshold) // TODO(tf) cognitive complexity > 25 (threshold)
    ...@@ -83,7 +83,6 @@ TEST(test_entity, test_from_id_response) { // NOLINT ...@@ -83,7 +83,6 @@ TEST(test_entity, test_from_id_response) { // NOLINT
    Entity entity(&idResponse); Entity entity(&idResponse);
    std::cout << entity.ToString() << std::endl;
    EXPECT_EQ(entity.GetId(), "entity_id"); EXPECT_EQ(entity.GetId(), "entity_id");
    EXPECT_EQ(entity.GetErrors().Size(), 1); EXPECT_EQ(entity.GetErrors().Size(), 1);
    EXPECT_EQ(entity.GetErrors().At(0).GetDescription(), "error_desc"); EXPECT_EQ(entity.GetErrors().At(0).GetDescription(), "error_desc");
    ...@@ -99,16 +98,19 @@ TEST(test_entity, test_from_id_response) { // NOLINT ...@@ -99,16 +98,19 @@ TEST(test_entity, test_from_id_response) { // NOLINT
    info->set_description("info_desc"); info->set_description("info_desc");
    info->set_code(MessageCode::UNSPECIFIED); info->set_code(MessageCode::UNSPECIFIED);
    std::cout << entity.ToString() << std::endl;
    Entity other_ent(&idr_warnings_and_infos); Entity other_ent(&idr_warnings_and_infos);
    std::cout << entity.ToString() << std::endl;
    EXPECT_EQ(other_ent.GetId(), "other_entity_id"); EXPECT_EQ(other_ent.GetId(), "other_entity_id");
    std::cout << entity.ToString() << std::endl;
    EXPECT_EQ(other_ent.GetWarnings().Size(), 1); EXPECT_EQ(other_ent.GetWarnings().Size(), 1);
    EXPECT_EQ(other_ent.GetWarnings().At(0).GetDescription(), "warning_desc"); EXPECT_EQ(other_ent.GetWarnings().At(0).GetDescription(), "warning_desc");
    EXPECT_EQ(other_ent.GetWarnings().At(0).GetCode(), EXPECT_EQ(other_ent.GetWarnings().At(0).GetCode(),
    MessageCode::ENTITY_HAS_NO_PROPERTIES); MessageCode::ENTITY_HAS_NO_PROPERTIES);
    std::cout << entity.ToString() << std::endl;
    EXPECT_EQ(other_ent.GetInfos().Size(), 1); EXPECT_EQ(other_ent.GetInfos().Size(), 1);
    EXPECT_EQ(other_ent.GetInfos().At(0).GetDescription(), "info_desc"); EXPECT_EQ(other_ent.GetInfos().At(0).GetDescription(), "info_desc");
    EXPECT_EQ(other_ent.GetInfos().At(0).GetCode(), MessageCode::UNSPECIFIED); EXPECT_EQ(other_ent.GetInfos().At(0).GetCode(), MessageCode::UNSPECIFIED);
    } }
    } // namespace caosdb::entity } // namespace caosdb::entity
    ...@@ -133,4 +133,17 @@ TEST(test_transaction, test_multi_result_set_three) { ...@@ -133,4 +133,17 @@ TEST(test_transaction, test_multi_result_set_three) {
    std::cout << rs.At(1).ToString(); std::cout << rs.At(1).ToString();
    } }
    TEST(test_transaction, test_update_entity) {
    const auto *host = "localhost";
    auto configuration = InsecureConnectionConfiguration(host, 8000);
    Connection connection(configuration);
    auto transaction = connection.CreateTransaction();
    caosdb::entity::Entity update_entity;
    update_entity.SetRole("New role");
    auto error = transaction->UpdateEntity(&update_entity);
    EXPECT_EQ(error, StatusCode::ORIGINAL_ENTITY_MISSING_ID);
    }
    } // namespace caosdb::transaction } // namespace caosdb::transaction
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment