Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_select.cpp 20.16 KiB
/*
 * This file is a part of the CaosDB Project.
 *
 * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
 * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
 * Copyright (C) 2021 Daniel Hornung <d.hornung@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/>.
 *
 */
#include "caosdb/connection.h"     // for Connection, ConnectionManager
#include "caosdb/data_type.h"      // for AtomicDataType
#include "caosdb/entity.h"         // for Entity, Property, Role, Parent
#include "caosdb/result_set.h"     // for Entity, ResultSet, ResultSet::ite...
#include "caosdb/result_table.h"   // for ResultTable::HeaderIterator, Resu...
#include "caosdb/transaction.h"    // for Transaction, ResultTable
#include "caosdb/value.h"          // for Value
#include <gtest/gtest-message.h>   // for Message
#include <gtest/gtest-spi.h>           // for EXPECT_NONFATAL_FA...
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl
#include <gtest/gtest_pred_impl.h> // for Test, TestInfo, EXPECT_EQ, TEST
#include <iostream>                // for operator<<, basic_ostream::operat...
#include <memory>                  // for allocator, unique_ptr, __shared_p...
#include <string>                  // for string

namespace caosdb::transaction {
using caosdb::entity::DataType;
using caosdb::entity::AtomicDataType;
using caosdb::entity::Entity;
using caosdb::entity::Parent;
using caosdb::entity::Property;
using caosdb::entity::Role;
using caosdb::entity::Value;

class test_select : public ::testing::Test {
public:
  static void InsertEntity(Entity *entity) {
    const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
    auto insert_transaction(connection->CreateTransaction());
    insert_transaction->InsertEntity(entity);
    insert_transaction->Execute();
  }

  static void DeleteEntities() {
    // delete all entities
    const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
    auto query_transaction(connection->CreateTransaction());
    query_transaction->Query("FIND Entity");
    // query_transaction->Query("FIND Test*");
    query_transaction->Execute();
    if (query_transaction->GetResultSet().size() > 0) {
      std::cout << "Cleanup: Deleting " << query_transaction->GetResultSet().size() << " entities."
                << std::endl;
      auto delete_transaction(connection->CreateTransaction());
      for (const Entity &entity : query_transaction->GetResultSet()) {
        delete_transaction->DeleteById(entity.GetId());
      }
      delete_transaction->Execute();
    }
  }

  static auto CreateTestProp(const std::string &name, AtomicDataType data_type) -> Entity {
    Entity entity;
    entity.SetRole(Role::PROPERTY);
    entity.SetName(name);
    entity.SetDescription("Prop Description " + name);
    entity.SetDataType(data_type);
    return entity;
  }

  static auto CreateTestRT() -> Entity {
    Entity entity;
    entity.SetRole(Role::RECORD_TYPE);
    entity.SetDescription("RT Description");
    entity.SetName("TestRT");
    return entity;
  }

  static auto CreateTestProp(const std::string &name, const std::string &data_type) -> Entity {
    Entity entity;
    entity.SetRole(Role::PROPERTY);
    entity.SetName(name);
    entity.SetDescription("Prop Description " + name);
    entity.SetDataType(data_type);
    return entity;
  }

  static auto CreateRecord(const std::string &property_name, const Value &value) -> Entity {
    Entity entity;
    entity.SetRole(Role::RECORD);
    Parent parent;
    parent.SetName("TestRT");
    entity.AppendParent(parent);
    Property property;
    property.SetName(property_name);
    property.SetValue(value);
    entity.AppendProperty(property);

    Property dummyProperty;
    dummyProperty.SetName("TestProp2");
    dummyProperty.SetValue("dummy value");
    entity.AppendProperty(dummyProperty);

    return entity;
  }

protected:
  // Fixture methods //////////////////////////////////////////////////////////

  void SetUp() override {
    DeleteEntities();

    const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
    auto insert_transaction(connection->CreateTransaction());
    auto rt = CreateTestRT();
    auto rt2 = CreateTestRT();
    rt2.SetName("TestRT2");
    insert_transaction->InsertEntity(&rt);
    insert_transaction->InsertEntity(&rt2);
    auto p = CreateTestProp("TestProp", AtomicDataType::TEXT);
    insert_transaction->InsertEntity(&p);
    p = CreateTestProp("TestProp2", AtomicDataType::TEXT);
    insert_transaction->InsertEntity(&p);
    p = CreateTestProp("TestProp3", AtomicDataType::TEXT);
    insert_transaction->InsertEntity(&p);
    p = CreateTestProp("TestPropDouble", AtomicDataType::DOUBLE);
    p.SetUnit("m");
    insert_transaction->InsertEntity(&p);
    p = CreateTestProp("TestPropInt", AtomicDataType::INTEGER);
    p.SetUnit("m");
    insert_transaction->InsertEntity(&p);
    p = CreateTestProp("TestPropBool", AtomicDataType::BOOLEAN);
    insert_transaction->InsertEntity(&p);


    auto reference_entity = test_select::CreateRecord("TestProp3", Value("val3"));
    Property property;
    property.SetName("TestPropDouble");
    property.SetUnit("km");
    property.SetValue(231.012);
    reference_entity.AppendProperty(property);

    reference_entity.RemoveParent(0);
    Parent parent;
    parent.SetName("TestRT2");
    reference_entity.AppendParent(parent);
    insert_transaction->InsertEntity(&reference_entity);
    insert_transaction->Execute();
  }

  void TearDown() override { DeleteEntities(); }
};

/*
 * Test select query on empty database.
 */
TEST_F(test_select, test_select_empty) {
  test_select::DeleteEntities();
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT name FROM RecordType TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "name");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 0);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("name").GetAsString(), "bla"); // should never be executed
  }
}

/*
 * Test select name query on record type.
 */
TEST_F(test_select, test_select_name) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT name FROM RecordType TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "name");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("name").GetAsString(), "TestRT");
  }
}

/*
 * Test select description query on record type.
 */
TEST_F(test_select, test_select_description) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT description FROM RecordType TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "description");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("description").GetAsString(), "RT Description");
  }
}

/*
 * Test select TestProp query on record.
 */
TEST_F(test_select, test_select_testprop) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto entity = test_select::CreateRecord("TestProp", Value("val1"));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestProp FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestProp");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestProp").GetAsString(), "val1");
  }
}

/*
 * Test select double value query on record.
 */
TEST_F(test_select, test_select_double) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto entity = test_select::CreateRecord("TestPropDouble", Value(2.123));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestPropDouble FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestPropDouble");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_TRUE(row.GetValue("TestPropDouble").IsDouble());
    EXPECT_EQ(row.GetValue("TestPropDouble").GetAsDouble(), 2.123);
  }
}

/*
 * Test select unit value query on record.
 */
TEST_F(test_select, test_select_unit) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto entity = test_select::CreateRecord("TestPropDouble", Value(2.123));
  test_select::InsertEntity(&entity);

  auto check(connection->CreateTransaction());
  check->Query("FIND Record TestRT");
  check->Execute();
  std::cout << check->GetResultSet().at(0).ToString() << std::endl;

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestPropDouble.unit FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestPropDouble.unit");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {

    // TODO(tf): create bug report: this is an insertion/update problem
    EXPECT_NONFATAL_FAILURE({ EXPECT_EQ(row.GetValue("TestPropDouble.unit").GetAsString(), "m"); }, "TestPropDouble.unit");
  }
}

/*
 * Test select int value query on record.
 */
TEST_F(test_select, test_select_int) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto entity = test_select::CreateRecord("TestPropInt", Value(1234));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestPropInt FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestPropInt");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_TRUE(row.GetValue("TestPropInt").IsInt64());
    EXPECT_EQ(row.GetValue("TestPropInt").GetAsInt64(), 1234);
  }
}

/* Test select boolean value query on record.  */ TEST_F(test_select, test_select_boolean) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto entity = test_select::CreateRecord("TestPropBool", Value(true));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestPropBool FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestPropBool");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_TRUE(row.GetValue("TestPropBool").IsBool());
    EXPECT_EQ(row.GetValue("TestPropBool").GetAsBool(), true);
  }
}

/*
 * Test select the referenced id.
 */
TEST_F(test_select, test_select_reference) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto get_id_of_ref_rec(connection->CreateTransaction());
  get_id_of_ref_rec->Query("SELECT id FROM RECORD TestRT2");
  get_id_of_ref_rec->Execute();
  auto id = (* get_id_of_ref_rec->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto entity = test_select::CreateRecord("TestRT2", Value(id));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestRT2 FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestRT2");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestRT2").GetAsString(), id);
  }
}

/*
 * Test select the referenced entity's property.
 */
TEST_F(test_select, test_select_reference_entitys_property) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto get_id_of_ref_rec(connection->CreateTransaction());
  get_id_of_ref_rec->Query("SELECT id FROM RECORD TestRT2");
  get_id_of_ref_rec->Execute();
  auto id = (* get_id_of_ref_rec->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto entity = test_select::CreateRecord("TestRT2", Value(id));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestRT2.TestProp3 FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestRT2.TestProp3");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestRT2.TestProp3").GetAsString(), "val3");
  }
}

/*
 * Test select the referenced entity's property's unit.
 */
TEST_F(test_select, test_select_reference_entitys_propertys_unit) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto get_id_of_ref_rec(connection->CreateTransaction());
  get_id_of_ref_rec->Query("SELECT id FROM RECORD TestRT2");
  get_id_of_ref_rec->Execute();
  auto id = (* get_id_of_ref_rec->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto entity = test_select::CreateRecord("TestRT2", Value(id));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestRT2.TestPropDouble.unit FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestRT2.TestPropDouble.unit");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestRT2.TestPropDouble.unit").GetAsString(), "km");
  }
}

/*
 * Test select the referenced entity's property's description.
 */
TEST_F(test_select, test_select_reference_entitys_propertys_description) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto get_id_of_ref_rec(connection->CreateTransaction());
  get_id_of_ref_rec->Query("SELECT id FROM RECORD TestRT2");
  get_id_of_ref_rec->Execute();
  auto id = (* get_id_of_ref_rec->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto entity = test_select::CreateRecord("TestRT2", Value(id));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestRT2.TestProp3.description FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestRT2.TestProp3.description");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestRT2.TestProp3.description").GetAsString(), "Prop Description TestProp3");
  }
}

/*
 * Test select the referenced entity's property's name.
 */
TEST_F(test_select, test_select_reference_entitys_propertys_name) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto get_id_of_ref_rec(connection->CreateTransaction());
  get_id_of_ref_rec->Query("SELECT id FROM RECORD TestRT2");
  get_id_of_ref_rec->Execute();
  auto id = (* get_id_of_ref_rec->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto entity = test_select::CreateRecord("TestRT2", Value(id));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestRT2.TestProp3.name FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestRT2.TestProp3.name");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestRT2.TestProp3.name").GetAsString(), "TestProp3");
  }
}

/*
 * Test select the referenced entity's property's id.
 */
TEST_F(test_select, test_select_reference_entitys_propertys_id) {
  const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
  auto get_id_of_ref_rec(connection->CreateTransaction());
  get_id_of_ref_rec->Query("SELECT id FROM RECORD TestRT2");
  get_id_of_ref_rec->Execute();
  auto id = (* get_id_of_ref_rec->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto get_id_of_prop(connection->CreateTransaction());
  get_id_of_prop->Query("SELECT id FROM PROPERTY TestProp3");
  get_id_of_prop->Execute();
  auto pid = (* get_id_of_prop->GetResultTable().GetRows().begin()).GetValue("id").GetAsString();

  auto entity = test_select::CreateRecord("TestRT2", Value(id));
  test_select::InsertEntity(&entity);

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("SELECT TestRT2.TestProp3.id FROM Record TestRT");
  query_transaction->Execute();
  EXPECT_EQ(query_transaction->GetResultTable().GetHeader().size(), 1);
  for (const auto &column : query_transaction->GetResultTable().GetHeader()) {
    EXPECT_EQ(column.GetName(), "TestRT2.TestProp3.id");
  }

  EXPECT_EQ(query_transaction->GetResultTable().size(), 1);
  for (const auto &row : query_transaction->GetResultTable().GetRows()) {
    EXPECT_EQ(row.GetValue("TestRT2.TestProp3.id").GetAsString(), pid);
  }
}


} // namespace caosdb::transaction