Skip to content
Snippets Groups Projects
test_transaction.cpp 22.7 KiB
Newer Older
/*
 * This file is a part of the CaosDB Project.
 *
 * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
 * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 *
 */
Timm Fitschen's avatar
Timm Fitschen committed
#include "caosdb/connection.h"         // for Connection, ConnectionManager
#include "caosdb/entity.h"             // for Entity, Messages, Message
#include "caosdb/message_code.h"       // for ENTITY_DOES_NOT_EXIST, Messag...
#include "caosdb/status_code.h"        // for SUCCESS, StatusCode
#include "caosdb/transaction.h"        // for Entity, Transaction, UniqueRe...
#include "caosdb/transaction_status.h" // for TransactionStatus, StatusCode
#include "gtest/gtest-message.h"       // for Message
#include "gtest/gtest-test-part.h"     // for TestPartResult, SuiteApiResolver
#include "gtest/gtest_pred_impl.h"     // for Test, EXPECT_EQ, AssertionResult
Timm Fitschen's avatar
Timm Fitschen committed
#include <memory>                      // for unique_ptr, allocator, __shar...
Timm Fitschen's avatar
Timm Fitschen committed
#include <string>                      // for string
Timm Fitschen's avatar
Timm Fitschen committed
#include <vector>                      // for vector
namespace caosdb::transaction {
Timm Fitschen's avatar
Timm Fitschen committed
using caosdb::entity::Entity;
Timm Fitschen's avatar
Timm Fitschen committed
using caosdb::entity::MessageCode;
using caosdb::entity::Parent;
using caosdb::entity::Property;
Timm Fitschen's avatar
Timm Fitschen committed
class test_transaction : public ::testing::Test {
protected:
  void SetUp() override {}
Timm Fitschen's avatar
Timm Fitschen committed

  void TearDown() override {
    const auto &connection =
      caosdb::connection::ConnectionManager::GetDefaultConnection();
    auto query_transaction(connection->CreateTransaction());
    query_transaction->Query("FIND ENTITY WITH id > 99");
    query_transaction->Execute();
    if (query_transaction->GetResultSet().Size() > 0) {
Timm Fitschen's avatar
Timm Fitschen committed
      auto delete_transaction(connection->CreateTransaction());
      for (const Entity &entity : query_transaction->GetResultSet()) {
        delete_transaction->DeleteById(entity.GetId());
      }
Timm Fitschen's avatar
Timm Fitschen committed
      delete_transaction->Execute();
Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, DISABLED_retrieve_manufacturer_by_id) {
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();
  const auto *id = "107";
  const auto *role = "RecordType";
  const auto *name = "Manufacturer";
  const auto *description = "A generic manufacturer of all kinds of products";
  const auto *version = "0bea8f7b17f0130fa5701a6c3849b9f8bfa0651b";

  auto transaction(connection->CreateTransaction());
  transaction->RetrieveById(id);
  transaction->Execute();

  const auto &result_set =
    dynamic_cast<const UniqueResult &>(transaction->GetResultSet());

  const auto &entity = result_set.GetEntity();
  EXPECT_EQ(id, entity.GetId());
  EXPECT_EQ(name, entity.GetName());
  EXPECT_EQ(role, entity.GetRole());
  EXPECT_EQ(description, entity.GetDescription());
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_EQ(version, entity.GetVersionId());
Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, retrieve_non_existing) {
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto transaction(connection->CreateTransaction());

  const auto *id = "non-existing-id";
  transaction->RetrieveById(id);
Timm Fitschen's avatar
Timm Fitschen committed
  transaction->ExecuteAsynchronously();
Timm Fitschen's avatar
Timm Fitschen committed
  auto status = transaction->WaitForIt();
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_EQ(status.GetCode(), TransactionStatus::TRANSACTION_ERROR().GetCode());
  ASSERT_EQ(status.GetCode(), StatusCode::GENERIC_TRANSACTION_ERROR);
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &result_set =
    dynamic_cast<const UniqueResult &>(transaction->GetResultSet());
Timm Fitschen's avatar
Timm Fitschen committed

  const auto &entity = result_set.GetEntity();
  EXPECT_EQ(id, entity.GetId());
  EXPECT_TRUE(entity.HasErrors());
  ASSERT_EQ(entity.GetErrors().Size(), 1);
  EXPECT_EQ(entity.GetErrors().At(0).GetCode(),
            MessageCode::ENTITY_DOES_NOT_EXIST);
Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, insert_without_delete) {
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto insert_transaction(connection->CreateTransaction());

  Entity entity;
  entity.SetRole("RecordType");
  entity.SetName("RT1");
  insert_transaction->InsertEntity(&entity);
  insert_transaction->ExecuteAsynchronously();

  auto insert_status = insert_transaction->WaitForIt();

  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());

  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());

  const auto &new_entity = insert_result_set.GetEntity();
  EXPECT_FALSE(new_entity.GetId().empty());
  EXPECT_FALSE(new_entity.HasErrors());
  // Should have a warning since it has no properties
  EXPECT_TRUE(new_entity.HasWarnings());
  EXPECT_EQ(new_entity.GetWarnings().Size(), 1);
  EXPECT_EQ(new_entity.GetWarnings().At(0).GetCode(),
            MessageCode::ENTITY_HAS_NO_PROPERTIES);
}

TEST_F(test_transaction, insert_delete) {
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

Timm Fitschen's avatar
Timm Fitschen committed
  auto insert_transaction(connection->CreateTransaction());
Timm Fitschen's avatar
Timm Fitschen committed

  Entity entity;
  entity.SetRole("RecordType");
  entity.SetName("RT1");
Timm Fitschen's avatar
Timm Fitschen committed
  insert_transaction->InsertEntity(&entity);
  insert_transaction->ExecuteAsynchronously();
Timm Fitschen's avatar
Timm Fitschen committed
  auto insert_status = insert_transaction->WaitForIt();
Timm Fitschen's avatar
Timm Fitschen committed
  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &new_entity = insert_result_set.GetEntity();
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_FALSE(new_entity.GetId().empty());
  EXPECT_FALSE(new_entity.HasErrors());
florian's avatar
florian committed
  // Should have a warning since it has no properties
  EXPECT_TRUE(new_entity.HasWarnings());
  EXPECT_EQ(new_entity.GetWarnings().Size(), 1);
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_EQ(new_entity.GetWarnings().At(0).GetCode(),
            MessageCode::ENTITY_HAS_NO_PROPERTIES);
Timm Fitschen's avatar
Timm Fitschen committed

  auto delete_transaction(connection->CreateTransaction());

  delete_transaction->DeleteById(new_entity.GetId());
  delete_transaction->ExecuteAsynchronously();

  auto delete_status = delete_transaction->WaitForIt();

  ASSERT_TRUE(delete_status.IsTerminated());
  ASSERT_FALSE(delete_status.IsError());

  const auto &delete_result_set =
    dynamic_cast<const UniqueResult &>(delete_transaction->GetResultSet());
Timm Fitschen's avatar
Timm Fitschen committed

  const auto &deleted_entity = delete_result_set.GetEntity();
  EXPECT_EQ(deleted_entity.GetId(), new_entity.GetId());
  EXPECT_FALSE(deleted_entity.HasErrors());
Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, insert_delete_with_parent) {
florian's avatar
florian committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto insert_transaction(connection->CreateTransaction());

  Entity rt;
  rt.SetRole("RecordType");
  rt.SetName("TestRT");
  insert_transaction->InsertEntity(&rt);
florian's avatar
florian committed
  insert_transaction->ExecuteAsynchronously();

  auto insert_status = insert_transaction->WaitForIt();

  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());

  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());

  const auto &inserted_rt = insert_result_set.GetEntity();
  Entity rec;
  rec.SetRole("Record");
  rec.SetName("TestRec");

  Parent parent;
  parent.SetName(rt.GetName());
florian's avatar
florian committed
  parent.SetId(inserted_rt.GetId());
  rec.AppendParent(parent);

  auto rec_transaction(connection->CreateTransaction());
  rec_transaction->InsertEntity(&rec);
  rec_transaction->ExecuteAsynchronously();

  auto rec_insert_status = rec_transaction->WaitForIt();

  ASSERT_TRUE(rec_insert_status.IsTerminated());
  ASSERT_FALSE(rec_insert_status.IsError());

  const auto &rec_result_set =
    dynamic_cast<const UniqueResult &>(rec_transaction->GetResultSet());

  const auto &inserted_rec = rec_result_set.GetEntity();

  EXPECT_FALSE(inserted_rec.GetId().empty());

  auto retrieve_transaction(connection->CreateTransaction());
  retrieve_transaction->RetrieveById(inserted_rec.GetId());

  retrieve_transaction->ExecuteAsynchronously();

  auto rec_retrieve_status = retrieve_transaction->WaitForIt();

  ASSERT_TRUE(rec_retrieve_status.IsTerminated());
  ASSERT_FALSE(rec_retrieve_status.IsError());

  const auto &retrieve_result_set =
    dynamic_cast<const UniqueResult &>(retrieve_transaction->GetResultSet());
  const auto &retrieved_rec = retrieve_result_set.GetEntity();

  EXPECT_EQ(retrieved_rec.GetName(), rec.GetName());
  EXPECT_EQ(retrieved_rec.GetParents().Size(), 1);
  EXPECT_EQ(retrieved_rec.GetParents().At(0).GetId(), inserted_rt.GetId());
  EXPECT_EQ(retrieved_rec.GetParents().At(0).GetName(), rt.GetName());

  auto rec_deletion(connection->CreateTransaction());

  rec_deletion->DeleteById(retrieved_rec.GetId());
  rec_deletion->ExecuteAsynchronously();

  auto rec_delete_status = rec_deletion->WaitForIt();

  ASSERT_TRUE(rec_delete_status.IsTerminated());
  ASSERT_FALSE(rec_delete_status.IsError());

  auto rt_deletion(connection->CreateTransaction());

  rt_deletion->DeleteById(inserted_rt.GetId());
  rt_deletion->ExecuteAsynchronously();

  auto rt_delete_status = rt_deletion->WaitForIt();

  ASSERT_TRUE(rt_delete_status.IsTerminated());
  ASSERT_FALSE(rt_delete_status.IsError());
florian's avatar
florian committed
}

Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, insert_delete_with_property) {
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  // Create and insert property
  Entity prop_ent;
  prop_ent.SetRole("Property");
  prop_ent.SetName("TestProperty");
  prop_ent.SetDatatype("TEXT");

  auto prop_insertion(connection->CreateTransaction());
  prop_insertion->InsertEntity(&prop_ent);
  prop_insertion->ExecuteAsynchronously();

  auto prop_insert_status = prop_insertion->WaitForIt();

  ASSERT_TRUE(prop_insert_status.IsTerminated());
  ASSERT_FALSE(prop_insert_status.IsError());

  const auto &prop_result_set =
    dynamic_cast<const UniqueResult &>(prop_insertion->GetResultSet());

  const auto &inserted_prop = prop_result_set.GetEntity();
  EXPECT_FALSE(inserted_prop.GetId().empty());

  // create and insert record type with the above property
  Property prop_rt;
  prop_rt.SetName(prop_ent.GetName());
  prop_rt.SetId(inserted_prop.GetId());
  prop_rt.SetImportance("SUGGESTED");

  Entity rt;
  rt.SetRole("RecordType");
  rt.SetName("TestRT");
florian's avatar
florian committed
  rt.SetDescription("Some description");
  rt.AppendProperty(prop_rt);

  auto rt_insertion(connection->CreateTransaction());
  rt_insertion->InsertEntity(&rt);
  rt_insertion->ExecuteAsynchronously();

  auto rt_insert_status = rt_insertion->WaitForIt();

  ASSERT_TRUE(rt_insert_status.IsTerminated());
  ASSERT_FALSE(rt_insert_status.IsError());

  const auto &rt_result_set =
    dynamic_cast<const UniqueResult &>(rt_insertion->GetResultSet());

  const auto &inserted_rt = rt_result_set.GetEntity();
  EXPECT_FALSE(inserted_rt.GetId().empty());

  // retrieve inserted rt for testing
  auto rt_retrieval(connection->CreateTransaction());
  rt_retrieval->RetrieveById(inserted_rt.GetId());
  rt_retrieval->ExecuteAsynchronously();

  auto rt_retrieve_status = rt_retrieval->WaitForIt();
  ASSERT_TRUE(rt_retrieve_status.IsTerminated());
  ASSERT_FALSE(rt_retrieve_status.IsError());

  const auto &rt_retrieve_results =
    dynamic_cast<const UniqueResult &>(rt_retrieval->GetResultSet());

  const auto &retrieved_rt = rt_retrieve_results.GetEntity();
  EXPECT_EQ(inserted_rt.GetId(), retrieved_rt.GetId());
  EXPECT_EQ(rt.GetName(), retrieved_rt.GetName());
florian's avatar
florian committed
  EXPECT_EQ(rt.GetDescription(), retrieved_rt.GetDescription());
  EXPECT_EQ(retrieved_rt.GetProperties().Size(), 1);

  const auto &retrieved_prop_rt = retrieved_rt.GetProperties().At(0);
  EXPECT_EQ(retrieved_prop_rt.GetName(), prop_ent.GetName());
  EXPECT_EQ(retrieved_prop_rt.GetId(), inserted_prop.GetId());
  EXPECT_EQ(retrieved_prop_rt.GetDatatype(), prop_ent.GetDatatype());
  EXPECT_EQ(retrieved_prop_rt.GetImportance(), prop_rt.GetImportance());

  // create and insert record of the above record type with a property
  // with a value.
  Parent parent;
  parent.SetName(rt.GetName());
  parent.SetId(inserted_rt.GetId());

  Property prop_rec;
  prop_rec.SetName(prop_ent.GetName());
  prop_rec.SetId(inserted_prop.GetId());
  prop_rec.SetValue("Test");

  Entity rec;
  rec.SetName("TestRec");
  rec.SetRole("Record");
  rec.AppendParent(parent);
  rec.AppendProperty(prop_rec);

  auto rec_insertion(connection->CreateTransaction());
  rec_insertion->InsertEntity(&rec);
  rec_insertion->ExecuteAsynchronously();

  auto rec_insert_status = rec_insertion->WaitForIt();

  ASSERT_TRUE(rec_insert_status.IsTerminated());
  ASSERT_FALSE(rec_insert_status.IsError());

  const auto &rec_result_set =
    dynamic_cast<const UniqueResult &>(rec_insertion->GetResultSet());

  const auto &inserted_rec = rec_result_set.GetEntity();
  EXPECT_FALSE(inserted_rec.GetId().empty());

  // Retrieve the record and verify paretn and property
  auto rec_retrieval(connection->CreateTransaction());
  rec_retrieval->RetrieveById(inserted_rec.GetId());
  rec_retrieval->ExecuteAsynchronously();

  auto rec_retrieve_status = rec_retrieval->WaitForIt();
  ASSERT_TRUE(rec_retrieve_status.IsTerminated());
  ASSERT_FALSE(rec_retrieve_status.IsError());

  const auto &rec_retrieve_results =
    dynamic_cast<const UniqueResult &>(rec_retrieval->GetResultSet());

  const auto &retrieved_rec = rec_retrieve_results.GetEntity();
  EXPECT_EQ(rec.GetName(), retrieved_rec.GetName());
  EXPECT_EQ(inserted_rec.GetId(), retrieved_rec.GetId());
  EXPECT_EQ(retrieved_rec.GetParents().Size(), 1);
  EXPECT_EQ(retrieved_rec.GetProperties().Size(), 1);

  const auto &retrieved_parent_rec = retrieved_rec.GetParents().At(0);
  EXPECT_EQ(retrieved_parent_rec.GetName(), rt.GetName());
  EXPECT_EQ(retrieved_parent_rec.GetId(), inserted_rt.GetId());
florian's avatar
florian committed
  EXPECT_EQ(retrieved_parent_rec.GetDescription(), rt.GetDescription());

  const auto &retrieved_prop_rec = retrieved_rec.GetProperties().At(0);
  EXPECT_EQ(retrieved_prop_rec.GetName(), prop_ent.GetName());
  EXPECT_EQ(retrieved_prop_rec.GetId(), inserted_prop.GetId());
  EXPECT_EQ(retrieved_prop_rec.GetDatatype(), prop_ent.GetDatatype());
  EXPECT_EQ(retrieved_prop_rec.GetValue(), prop_rec.GetValue());
florian's avatar
florian committed

Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, test_multi_retrieve) {
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto transaction(connection->CreateTransaction());

  const std::vector<std::string> ids = {"20", "21", "22"};
  transaction->RetrieveById(ids.begin(), ids.end());
  transaction->ExecuteAsynchronously();

  auto status = transaction->WaitForIt();

  ASSERT_TRUE(status.IsTerminated());
  ASSERT_FALSE(status.IsError());

  const auto &result_set = transaction->GetResultSet();

  EXPECT_EQ(result_set.Size(), 3);
  EXPECT_EQ(result_set.At(1).GetId(), "21");
  EXPECT_EQ(result_set.At(1).GetName(), "unit");
  EXPECT_FALSE(result_set.At(1).HasErrors());

  EXPECT_EQ(result_set.At(2).GetId(), "22");
  EXPECT_TRUE(result_set.At(2).HasErrors());
  EXPECT_EQ(result_set.At(2).GetErrors().At(0).GetCode(),
            MessageCode::ENTITY_DOES_NOT_EXIST);
Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, insert_update_delete) {
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  // INSERT
  auto insert_transaction(connection->CreateTransaction());

  Entity entity;
  entity.SetRole("RecordType");
  entity.SetName("RT1");
  insert_transaction->InsertEntity(&entity);
  insert_transaction->ExecuteAsynchronously();

  auto insert_status = insert_transaction->WaitForIt();

  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());

  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());

  const auto &new_entity = insert_result_set.GetEntity();
  EXPECT_FALSE(new_entity.GetId().empty());
  EXPECT_FALSE(new_entity.HasErrors());

Timm Fitschen's avatar
Timm Fitschen committed
  // RETRIEVE
  auto retrieve_transaction(connection->CreateTransaction());
  retrieve_transaction->RetrieveById(new_entity.GetId());
  retrieve_transaction->Execute();

Timm Fitschen's avatar
Timm Fitschen committed
  // UPDATE
  auto update_transaction(connection->CreateTransaction());
Timm Fitschen's avatar
Timm Fitschen committed
  auto update_entity(retrieve_transaction->GetResultSet().At(0));
Timm Fitschen's avatar
Timm Fitschen committed
  update_entity.SetName("RT1-Update");

Timm Fitschen's avatar
Timm Fitschen committed
  update_transaction->UpdateEntity(&update_entity);
Timm Fitschen's avatar
Timm Fitschen committed
  update_transaction->ExecuteAsynchronously();
Timm Fitschen's avatar
Timm Fitschen committed

Timm Fitschen's avatar
Timm Fitschen committed
  auto update_status = update_transaction->WaitForIt();
Timm Fitschen's avatar
Timm Fitschen committed
  ASSERT_TRUE(update_status.IsTerminated());
  ASSERT_FALSE(update_status.IsError());

  EXPECT_EQ(update_transaction->GetResultSet().Size(), 1);
  const auto &updated_entity = update_transaction->GetResultSet().At(0);
Timm Fitschen's avatar
Timm Fitschen committed

  EXPECT_EQ(updated_entity.GetId(), new_entity.GetId());
  EXPECT_FALSE(updated_entity.HasErrors());

  // DELETE
  auto delete_transaction(connection->CreateTransaction());

  delete_transaction->DeleteById(new_entity.GetId());
  delete_transaction->ExecuteAsynchronously();

  auto delete_status = delete_transaction->WaitForIt();

  ASSERT_TRUE(delete_status.IsTerminated());
  ASSERT_FALSE(delete_status.IsError());

  const auto &delete_result_set =
    dynamic_cast<const UniqueResult &>(delete_transaction->GetResultSet());

  const auto &deleted_entity = delete_result_set.GetEntity();
  EXPECT_EQ(deleted_entity.GetId(), new_entity.GetId());
  EXPECT_FALSE(deleted_entity.HasErrors());
}

Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, test_query) {
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto insert_transaction(connection->CreateTransaction());

  Entity entity;
  entity.SetRole("RecordType");
  entity.SetName("RT1");
  insert_transaction->InsertEntity(&entity);
  insert_transaction->ExecuteAsynchronously();

  auto insert_status = insert_transaction->WaitForIt();

  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());

  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());

  const auto &new_entity = insert_result_set.GetEntity();
  EXPECT_FALSE(new_entity.GetId().empty());
  EXPECT_FALSE(new_entity.HasErrors());

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("FIND ENTITY WITH id = " + new_entity.GetId());
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultSet().Size(), 1);
  EXPECT_EQ(query_transaction->GetResultSet().At(0).GetId(),
            new_entity.GetId());
florian's avatar
florian committed
  // No count query, so no count result should be present
  EXPECT_TRUE((query_transaction->GetCountResult() < 0));

  auto count_query_trans(connection->CreateTransaction());
  count_query_trans->Query("COUNT ENTITY WITH id = " + new_entity.GetId());
  count_query_trans->Execute();
  // No result set in a count query
  EXPECT_EQ(count_query_trans->GetResultSet().Size(), 0);
  EXPECT_EQ(count_query_trans->GetCountResult(), 1);
Timm Fitschen's avatar
Timm Fitschen committed
}

Timm Fitschen's avatar
Timm Fitschen committed
TEST_F(test_transaction, test_query_with_retrieve) {
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  // rt1
  Entity rt1;
  rt1.SetRole("RecordType");
  rt1.SetName("TestRT1");

  auto insert_rt1_transaction(connection->CreateTransaction());
  insert_rt1_transaction->InsertEntity(&rt1);
  insert_rt1_transaction->ExecuteAsynchronously();

  auto insert_rt1_status = insert_rt1_transaction->WaitForIt();

  ASSERT_TRUE(insert_rt1_status.IsTerminated());
  ASSERT_FALSE(insert_rt1_status.IsError());

  const auto &insert_rt1_results =
    dynamic_cast<const UniqueResult &>(insert_rt1_transaction->GetResultSet());

  const auto &inserted_rt1 = insert_rt1_results.GetEntity();
  EXPECT_FALSE(inserted_rt1.GetId().empty());
  EXPECT_FALSE(inserted_rt1.HasErrors());

  // rt2
  Entity rt2;
  rt2.SetRole("RecordType");
  rt2.SetName("TestRT2");

  auto insert_rt2_transaction(connection->CreateTransaction());
  insert_rt2_transaction->InsertEntity(&rt2);
  insert_rt2_transaction->ExecuteAsynchronously();

  auto insert_rt2_status = insert_rt2_transaction->WaitForIt();

  ASSERT_TRUE(insert_rt2_status.IsTerminated());
  ASSERT_FALSE(insert_rt2_status.IsError());

  const auto &insert_rt2_results =
    dynamic_cast<const UniqueResult &>(insert_rt2_transaction->GetResultSet());

  const auto &inserted_rt2 = insert_rt2_results.GetEntity();
  EXPECT_FALSE(inserted_rt2.GetId().empty());
  EXPECT_FALSE(inserted_rt2.HasErrors());

  // rt3
  Entity rt3;
  rt3.SetRole("RecordType");
  rt3.SetName("TestRT3");

  auto insert_rt3_transaction(connection->CreateTransaction());
  insert_rt3_transaction->InsertEntity(&rt3);
  insert_rt3_transaction->ExecuteAsynchronously();

  auto insert_rt3_status = insert_rt3_transaction->WaitForIt();

  ASSERT_TRUE(insert_rt3_status.IsTerminated());
  ASSERT_FALSE(insert_rt3_status.IsError());

  const auto &insert_rt3_results =
    dynamic_cast<const UniqueResult &>(insert_rt3_transaction->GetResultSet());

  const auto &inserted_rt3 = insert_rt3_results.GetEntity();
  EXPECT_FALSE(inserted_rt3.GetId().empty());
  EXPECT_FALSE(inserted_rt3.HasErrors());

florian's avatar
florian committed
  // only FIND
  auto find_transaction(connection->CreateTransaction());
  find_transaction->Query("FIND ENTITY WITH name LIKE 'TestRT*'");
  find_transaction->ExecuteAsynchronously();

  const auto find_status = find_transaction->WaitForIt();

  ASSERT_TRUE(find_status.IsTerminated());
  ASSERT_FALSE(find_status.IsError());

  const auto &find_results = find_transaction->GetResultSet();
  EXPECT_EQ(find_results.Size(), 3);

  // only retrieve rt1 and rt2 by id
  const std::vector<std::string> ids = {inserted_rt1.GetId(),
                                        inserted_rt2.GetId()};

  // retrieve rt3 with a FIND query
  auto find_and_retrieve(connection->CreateTransaction());
  find_and_retrieve->Query("FIND ENTITY WITH id = " + inserted_rt3.GetId());
  find_and_retrieve->RetrieveById(ids.begin(), ids.end());
  find_and_retrieve->ExecuteAsynchronously();

  auto find_and_retrieve_status = find_and_retrieve->WaitForIt();

  ASSERT_TRUE(find_and_retrieve_status.IsTerminated());
  ASSERT_FALSE(find_and_retrieve_status.IsError());

  const auto &result_set_a = find_and_retrieve->GetResultSet();
  EXPECT_EQ(result_set_a.Size(), 3);

  // retrieve rt1 and rt2 by ID and count all TestRTs
  auto count_and_retrieve(connection->CreateTransaction());
  count_and_retrieve->Query("COUNT ENTITY WITH name LIKE 'TestRT*'");
  count_and_retrieve->RetrieveById(ids.begin(), ids.end());
  count_and_retrieve->ExecuteAsynchronously();

  auto count_and_retrieve_status = count_and_retrieve->WaitForIt();

  ASSERT_TRUE(count_and_retrieve_status.IsTerminated());
  ASSERT_FALSE(count_and_retrieve_status.IsError());

  const auto &result_set_b = count_and_retrieve->GetResultSet();
florian's avatar
florian committed
  // TODO(fspreck) Re-enable once we implemented this
  // EXPECT_EQ(result_set_b.Size(), 2);
  EXPECT_EQ(count_and_retrieve->GetCountResult(), 3);
}
} // namespace caosdb::transaction