From b62599d8407bd6b71aae7d2a65b93ff3c9693f44 Mon Sep 17 00:00:00 2001
From: florian <f.spreckelsen@inidscale.com>
Date: Wed, 15 Sep 2021 14:00:12 +0200
Subject: [PATCH] ENH: Implement creators and destructor for datatypes

---
 src/ccaosdb.cpp       | 50 ++++++++++++++++++++++++++++++++++++-------
 test/test_ccaosdb.cpp | 33 +++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/src/ccaosdb.cpp b/src/ccaosdb.cpp
index cf1d75b..5079f11 100644
--- a/src/ccaosdb.cpp
+++ b/src/ccaosdb.cpp
@@ -48,7 +48,7 @@ extern "C" {
 
 #define WRAPPED_MESSAGE_CAST(name) static_cast<caosdb::entity::Message *>(name->wrapped_message)
 
-#define WRAPPED_DATATYPE_CAST(name) static_cast<caosdb::entity::Datatype *>(name->wrapped_datatype)
+#define WRAPPED_DATATYPE_CAST(name) static_cast<caosdb::entity::DataType *>(name->wrapped_datatype)
 
 #define WRAPPED_VALUE_CAST(name) static_cast<caosdb::entity::AbstractValue *>(name->wrapped_value)
 
@@ -163,9 +163,7 @@ extern "C" {
 #define CREATE_VALUE(fname, arg)                                                                   \
   ERROR_RETURN_CODE(GENERIC_ERROR,                                                                 \
                     int caosdb_entity_create_##fname(caosdb_entity_value *out, arg), {             \
-                      if (out->_deletable) {                                                       \
-                        return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;                      \
-                      }                                                                            \
+                      RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)                                   \
                       out->wrapped_value = new caosdb::entity::Value(value);                       \
                       out->_deletable = true;                                                      \
                       return 0;                                                                    \
@@ -693,19 +691,55 @@ ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_parent(caosdb_entity_p
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_create_atomic_datatype(caosdb_entity_datatype *out,
                                                            const char *name),
-                  {})
+                  {
+                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    try {
+                      auto enum_value = ENUM_VALUE_FROM_NAME(std::string(name), AtomicDataType);
+                      out->wrapped_datatype = new caosdb::entity::DataType(enum_value);
+                      out->_deletable = true;
+                      return 0;
+                    } catch (const std::out_of_range &exc) {
+                      caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what());
+                      return caosdb::StatusCode::ENUM_MAPPING_ERROR;
+                    }
+                  })
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_create_reference_datatype(caosdb_entity_datatype *out,
                                                               const char *name),
-                  {})
+                  {
+                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    out->wrapped_datatype = new caosdb::entity::DataType(std::string(name));
+                    out->_deletable = true;
+                    return 0;
+                  })
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_create_atomic_list_datatype(caosdb_entity_datatype *out,
                                                                 const char *name),
-                  {})
+                  {
+                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    try {
+                      auto enum_value = ENUM_VALUE_FROM_NAME(std::string(name), AtomicDataType);
+                      out->wrapped_datatype = new caosdb::entity::DataType();
+                      auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(out);
+                      wrapped_datatype->ListOf(enum_value);
+                      out->_deletable = true;
+                      return 0;
+                    } catch (const std::out_of_range &exc) {
+                      caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what());
+                      return caosdb::StatusCode::ENUM_MAPPING_ERROR;
+                    }
+                  })
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_create_reference_list_datatype(caosdb_entity_datatype *out,
                                                                    const char *name),
-                  {})
+                  {
+                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    out->wrapped_datatype = new caosdb::entity::DataType();
+                    auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(out);
+                    wrapped_datatype->ListOf(std::string(name));
+                    out->_deletable = true;
+                    return 0;
+                  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_datatype(caosdb_entity_datatype *out), {
   if (out->_deletable) {
diff --git a/test/test_ccaosdb.cpp b/test/test_ccaosdb.cpp
index 4322c13..ac01dd0 100644
--- a/test/test_ccaosdb.cpp
+++ b/test/test_ccaosdb.cpp
@@ -127,6 +127,38 @@ TEST_F(test_ccaosdb, test_query) {
   EXPECT_EQ(return_code, 0);
 }
 
+TEST_F(test_ccaosdb, test_datatype) {
+
+  caosdb_entity_datatype atomic;
+  // check that this fails
+  int return_code(caosdb_entity_create_atomic_datatype(&atomic, "some type"));
+  EXPECT_EQ(return_code, caosdb::StatusCode::ENUM_MAPPING_ERROR);
+
+  return_code = caosdb_entity_create_atomic_datatype(&atomic, "INTEGER");
+  EXPECT_EQ(return_code, 0);
+
+  caosdb_entity_datatype reference;
+  return_code = caosdb_entity_create_reference_datatype(&reference, "MyType");
+  EXPECT_EQ(return_code, 0);
+
+  caosdb_entity_datatype list_of_atomics;
+  return_code = caosdb_entity_create_reference_datatype(&list_of_atomics, "DATETIME");
+  EXPECT_EQ(return_code, 0);
+
+  caosdb_entity_datatype list_of_references;
+  return_code = caosdb_entity_create_reference_datatype(&list_of_references, "MyType");
+  EXPECT_EQ(return_code, 0);
+
+  return_code = caosdb_entity_delete_datatype(&atomic);
+  EXPECT_EQ(return_code, 0);
+  return_code = caosdb_entity_delete_datatype(&reference);
+  EXPECT_EQ(return_code, 0);
+  return_code = caosdb_entity_delete_datatype(&list_of_atomics);
+  EXPECT_EQ(return_code, 0);
+  return_code = caosdb_entity_delete_datatype(&list_of_references);
+  EXPECT_EQ(return_code, 0);
+}
+
 TEST_F(test_ccaosdb, test_value) {
 
   caosdb_entity_value string_value;
@@ -207,7 +239,6 @@ TEST_F(test_ccaosdb, test_value) {
   caosdb_entity_value_is_vector(&bool_vector_value, &is_a);
   EXPECT_TRUE(is_a);
 
-  // TODO(fspreck) Test as... functions
   char *out_string = nullptr; // NOLINT
   return_code = caosdb_entity_value_get_as_string(&string_value, &out_string);
   EXPECT_EQ(return_code, 0);
-- 
GitLab