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

Merge branch 'f-query' into dev

parents b339a6b5 17acd8db
Branches
Tags
1 merge request!7ENH: Support FIND and COUNT queries
Pipeline #11714 passed
Pipeline: caosdb-cppinttest

#11725

    ...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
    cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
    set(libcaosdb_VERSION 0.0.9) set(libcaosdb_VERSION 0.0.10)
    set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0) set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0)
    set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5) set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5)
    set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0) set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0)
    ......
    ...@@ -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.9" version = "0.0.10"
    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"
    ......
    ...@@ -208,7 +208,7 @@ private: ...@@ -208,7 +208,7 @@ private:
    class MultiResultSet : public ResultSet { class MultiResultSet : public ResultSet {
    public: public:
    ~MultiResultSet() = default; ~MultiResultSet() = default;
    explicit MultiResultSet(MultiTransactionResponse *response); explicit MultiResultSet(std::vector<std::unique_ptr<Entity>> result_set);
    [[nodiscard]] inline auto Size() const noexcept -> int override { [[nodiscard]] inline auto Size() const noexcept -> int override {
    return this->entities.size(); return this->entities.size();
    } }
    ...@@ -357,6 +357,17 @@ public: ...@@ -357,6 +357,17 @@ public:
    return *result_set; return *result_set;
    } }
    /**
    * Return the result of a count query
    *
    * Only meaningful if there was exactly one COUNT query executed in
    * this transaction. In all other cases, the return value will be
    * -1.
    */
    [[nodiscard]] inline auto GetCountResult() const -> long {
    return query_count;
    }
    /** /**
    * Return the number of sub-requests in this transaction. * Return the number of sub-requests in this transaction.
    * *
    ...@@ -367,6 +378,23 @@ public: ...@@ -367,6 +378,23 @@ public:
    return this->request->requests_size(); return this->request->requests_size();
    } }
    /**
    * Get a JSON representation of the response.
    *
    * For debugging.
    */
    inline auto ResponseToString() const -> const std::string {
    google::protobuf::util::JsonOptions options;
    std::string out;
    google::protobuf::util::MessageToJsonString(*this->response, &out, options);
    return out;
    }
    /**
    * Get a JSON representation of the request.
    *
    * For debugging.
    */
    inline auto RequestToString() const -> const std::string { inline auto RequestToString() const -> const std::string {
    google::protobuf::util::JsonOptions options; google::protobuf::util::JsonOptions options;
    std::string out; std::string out;
    ...@@ -383,6 +411,7 @@ private: ...@@ -383,6 +411,7 @@ private:
    MultiTransactionRequest *request; MultiTransactionRequest *request;
    mutable MultiTransactionResponse *response; mutable MultiTransactionResponse *response;
    std::string error_message; std::string error_message;
    mutable long query_count;
    }; };
    template <class InputIterator> template <class InputIterator>
    ......
    ...@@ -96,6 +96,8 @@ using caosdb::entity::v1alpha1::MultiTransactionRequest; ...@@ -96,6 +96,8 @@ using caosdb::entity::v1alpha1::MultiTransactionRequest;
    using caosdb::entity::v1alpha1::MultiTransactionResponse; using caosdb::entity::v1alpha1::MultiTransactionResponse;
    using WrappedResponseCase = using WrappedResponseCase =
    caosdb::entity::v1alpha1::TransactionResponse::WrappedResponseCase; caosdb::entity::v1alpha1::TransactionResponse::WrappedResponseCase;
    using QueryResponseCase =
    caosdb::entity::v1alpha1::RetrieveResponse::QueryResponseCase;
    using caosdb::utility::get_arena; using caosdb::utility::get_arena;
    using grpc::ClientAsyncResponseReader; using grpc::ClientAsyncResponseReader;
    using ProtoEntity = caosdb::entity::v1alpha1::Entity; using ProtoEntity = caosdb::entity::v1alpha1::Entity;
    ...@@ -131,28 +133,8 @@ auto ResultSet::end() const -> ResultSet::iterator { ...@@ -131,28 +133,8 @@ auto ResultSet::end() const -> ResultSet::iterator {
    return ResultSet::iterator(this, Size()); return ResultSet::iterator(this, Size());
    } }
    MultiResultSet::MultiResultSet(MultiTransactionResponse *response) { MultiResultSet::MultiResultSet(std::vector<std::unique_ptr<Entity>> result_set)
    auto *responses = response->mutable_responses(); : entities(std::move(result_set)) {}
    for (auto sub_response : *responses) {
    switch (sub_response.wrapped_response_case()) {
    case WrappedResponseCase::kRetrieveResponse:
    this->entities.push_back(std::make_unique<Entity>(
    sub_response.mutable_retrieve_response()->release_entity()));
    break;
    case WrappedResponseCase::kInsertResponse:
    this->entities.push_back(
    std::make_unique<Entity>(sub_response.release_insert_response()));
    break;
    case WrappedResponseCase::kDeleteResponse:
    this->entities.push_back(
    std::make_unique<Entity>(sub_response.release_insert_response()));
    break;
    default:
    // TODO(tf) Updates
    break;
    }
    }
    }
    [[nodiscard]] auto UniqueResult::GetEntity() const -> const Entity & { [[nodiscard]] auto UniqueResult::GetEntity() const -> const Entity & {
    const Entity *result = this->entity.get(); const Entity *result = this->entity.get();
    ...@@ -166,6 +148,7 @@ Transaction::Transaction( ...@@ -166,6 +148,7 @@ Transaction::Transaction(
    response(google::protobuf::Arena::CreateMessage<MultiTransactionResponse>( response(google::protobuf::Arena::CreateMessage<MultiTransactionResponse>(
    get_arena())) { get_arena())) {
    this->service_stub = std::move(service_stub); this->service_stub = std::move(service_stub);
    this->query_count = -1;
    } }
    auto Transaction::RetrieveById(const std::string &id) noexcept -> StatusCode { auto Transaction::RetrieveById(const std::string &id) noexcept -> StatusCode {
    ...@@ -197,7 +180,7 @@ auto Transaction::DeleteById(const std::string &id) noexcept -> StatusCode { ...@@ -197,7 +180,7 @@ auto Transaction::DeleteById(const std::string &id) noexcept -> StatusCode {
    auto *sub_request = this->request->add_requests(); auto *sub_request = this->request->add_requests();
    sub_request->mutable_delete_request()->set_id(id); sub_request->mutable_delete_request()->set_id(id);
    this->status = TransactionStatus::READY(); this->status = TransactionStatus::GO_ON();
    return this->status.GetCode(); return this->status.GetCode();
    } }
    ...@@ -300,13 +283,30 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { ...@@ -300,13 +283,30 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus {
    auto *responses = this->response->mutable_responses(0); auto *responses = this->response->mutable_responses(0);
    switch (responses->wrapped_response_case()) { switch (responses->wrapped_response_case()) {
    case WrappedResponseCase::kRetrieveResponse: { case WrappedResponseCase::kRetrieveResponse: {
    auto *entity = responses->mutable_retrieve_response()->release_entity(); auto *retrieve_response = responses->mutable_retrieve_response();
    switch (retrieve_response->query_response_case()) {
    case QueryResponseCase::kEntity: {
    auto *entity = retrieve_response->release_entity();
    if (!entity->errors().empty()) { if (!entity->errors().empty()) {
    this->status = TransactionStatus::TRANSACTION_ERROR( this->status = TransactionStatus::TRANSACTION_ERROR(
    "The request returned with errors."); "The request returned with errors.");
    } }
    this->result_set = std::make_unique<UniqueResult>(entity); this->result_set = std::make_unique<UniqueResult>(entity);
    } break; } break;
    case QueryResponseCase::kSelectResult: {
    // TODO(tf) Select queries
    } break;
    case QueryResponseCase::kCountResult: {
    this->query_count = retrieve_response->count_result();
    std::vector<std::unique_ptr<Entity>> entities;
    this->result_set =
    std::make_unique<MultiResultSet>(std::move(entities));
    } break;
    default:
    // TODO(tf) Error
    break;
    }
    } break;
    case WrappedResponseCase::kUpdateResponse: { case WrappedResponseCase::kUpdateResponse: {
    auto *updatedIdResponse = responses->mutable_update_response(); auto *updatedIdResponse = responses->mutable_update_response();
    if (!updatedIdResponse->entity_errors().empty()) { if (!updatedIdResponse->entity_errors().empty()) {
    ...@@ -336,7 +336,28 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { ...@@ -336,7 +336,28 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus {
    break; break;
    } }
    } else { } else {
    this->result_set = std::make_unique<MultiResultSet>(this->response); auto *responses = this->response->mutable_responses();
    std::vector<std::unique_ptr<Entity>> entities;
    for (auto sub_response : *responses) {
    switch (sub_response.wrapped_response_case()) {
    case WrappedResponseCase::kRetrieveResponse:
    entities.push_back(std::make_unique<Entity>(
    sub_response.mutable_retrieve_response()->release_entity()));
    break;
    case WrappedResponseCase::kInsertResponse:
    entities.push_back(
    std::make_unique<Entity>(sub_response.release_insert_response()));
    break;
    case WrappedResponseCase::kDeleteResponse:
    entities.push_back(
    std::make_unique<Entity>(sub_response.release_insert_response()));
    break;
    default:
    // TODO(tf) Updates
    break;
    }
    }
    this->result_set = std::make_unique<MultiResultSet>(std::move(entities));
    } }
    return this->status; return this->status;
    ......
    ...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
    #include "gtest/gtest_pred_impl.h" // for Test, TestInfo, TEST #include "gtest/gtest_pred_impl.h" // for Test, TestInfo, TEST
    #include <memory> // for allocator, unique_ptr #include <memory> // for allocator, unique_ptr
    #include <string> // for string, basic_string #include <string> // for string, basic_string
    #include <utility> // for move
    #include <vector> // for vector #include <vector> // for vector
    namespace caosdb::transaction { namespace caosdb::transaction {
    ...@@ -39,6 +40,7 @@ using caosdb::connection::Connection; ...@@ -39,6 +40,7 @@ using caosdb::connection::Connection;
    using caosdb::exceptions::ConnectionError; using caosdb::exceptions::ConnectionError;
    using caosdb::transaction::UniqueResult; using caosdb::transaction::UniqueResult;
    using ProtoEntity = caosdb::entity::v1alpha1::Entity; using ProtoEntity = caosdb::entity::v1alpha1::Entity;
    using caosdb::entity::v1alpha1::RetrieveResponse;
    TEST(test_transaction, create_transaction) { TEST(test_transaction, create_transaction) {
    const auto *host = "localhost"; const auto *host = "localhost";
    ...@@ -92,21 +94,18 @@ TEST(test_transaction, test_retrieve_by_ids) { ...@@ -92,21 +94,18 @@ TEST(test_transaction, test_retrieve_by_ids) {
    } }
    TEST(test_transaction, test_multi_result_set_empty) { TEST(test_transaction, test_multi_result_set_empty) {
    MultiTransactionResponse response; std::vector<std::unique_ptr<Entity>> empty;
    MultiResultSet rs(std::move(empty));
    MultiResultSet rs(&response);
    EXPECT_EQ(rs.Size(), 0); EXPECT_EQ(rs.Size(), 0);
    } }
    TEST(test_transaction, test_multi_result_iterator) { TEST(test_transaction, test_multi_result_iterator) {
    MultiTransactionResponse response; std::vector<std::unique_ptr<Entity>> one_elem;
    RetrieveResponse response;
    response.add_responses() response.mutable_entity()->set_id("100");
    ->mutable_retrieve_response() one_elem.push_back(std::make_unique<Entity>(response.release_entity()));
    ->mutable_entity()
    ->set_id("100");
    MultiResultSet rs(&response); MultiResultSet rs(std::move(one_elem));
    EXPECT_EQ(rs.Size(), 1); EXPECT_EQ(rs.Size(), 1);
    for (const Entity &entity : rs) { for (const Entity &entity : rs) {
    ...@@ -126,18 +125,19 @@ TEST(test_transaction, test_unique_result_iterator) { ...@@ -126,18 +125,19 @@ TEST(test_transaction, test_unique_result_iterator) {
    } }
    TEST(test_transaction, test_multi_result_set_one) { TEST(test_transaction, test_multi_result_set_one) {
    MultiTransactionResponse response; std::vector<std::unique_ptr<Entity>> one_elem;
    response.add_responses() RetrieveResponse response;
    ->mutable_retrieve_response() response.mutable_entity()->set_id("100");
    ->mutable_entity() one_elem.push_back(std::make_unique<Entity>(response.release_entity()));
    ->set_id("100");
    MultiResultSet rs(&response); MultiResultSet rs(std::move(one_elem));
    EXPECT_EQ(rs.Size(), 1); EXPECT_EQ(rs.Size(), 1);
    EXPECT_EQ(rs.At(0).GetId(), "100"); EXPECT_EQ(rs.At(0).GetId(), "100");
    } }
    TEST(test_transaction, test_multi_result_set_three) { TEST(test_transaction, test_multi_result_set_three) {
    std::vector<std::unique_ptr<Entity>> three_elem;
    MultiTransactionResponse response; MultiTransactionResponse response;
    response.add_responses() response.add_responses()
    ->mutable_retrieve_response() ->mutable_retrieve_response()
    ...@@ -152,7 +152,14 @@ TEST(test_transaction, test_multi_result_set_three) { ...@@ -152,7 +152,14 @@ TEST(test_transaction, test_multi_result_set_three) {
    ->mutable_entity() ->mutable_entity()
    ->set_id("102"); ->set_id("102");
    MultiResultSet rs(&response); auto *responses = response.mutable_responses();
    std::vector<std::unique_ptr<Entity>> entities;
    for (auto sub_response : *responses) {
    three_elem.push_back(std::make_unique<Entity>(
    sub_response.mutable_retrieve_response()->release_entity()));
    }
    MultiResultSet rs(std::move(three_elem));
    EXPECT_EQ(rs.Size(), 3); EXPECT_EQ(rs.Size(), 3);
    EXPECT_TRUE(rs.At(1).HasErrors()); EXPECT_TRUE(rs.At(1).HasErrors());
    } }
    ...@@ -170,4 +177,16 @@ TEST(test_transaction, test_update_entity) { ...@@ -170,4 +177,16 @@ TEST(test_transaction, test_update_entity) {
    EXPECT_EQ(error, StatusCode::ORIGINAL_ENTITY_MISSING_ID); EXPECT_EQ(error, StatusCode::ORIGINAL_ENTITY_MISSING_ID);
    } }
    TEST(test_transaction, test_multi_deletion) {
    const auto *host = "localhost";
    auto configuration = InsecureConnectionConfiguration(host, 8000);
    Connection connection(configuration);
    auto transaction = connection.CreateTransaction();
    EXPECT_EQ(transaction->GetStatus().GetCode(), StatusCode::INITIAL);
    for (int i = 0; i < 3; i++) {
    auto status = transaction->DeleteById("asdf");
    EXPECT_EQ(status, StatusCode::GO_ON);
    }
    }
    } // 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