From 7c6601d8874edaf0826a5b40499e0fdb632ceabe Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Tue, 9 Nov 2021 16:24:15 +0100
Subject: [PATCH] fix test clients

---
 CMakeLists.txt                |  42 +++++-------
 include/ccaosdb.h             |  30 +++++----
 src/caosdb/authentication.cpp |  16 +++--
 src/ccaosdb.cpp               | 117 ++++++++++++++++------------------
 src/cxxcaosdbcli.cpp          |  21 +++---
 5 files changed, 106 insertions(+), 120 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3fd25f..f5cb9b4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,7 +39,7 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+option(BUILD_SHARED_LIBCCAOSDB "Build libccaosdb as a shared library, based on a static libcaosdb" ON)
 
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 
@@ -51,14 +51,6 @@ IF (WIN32)
     cmake_minimum_required(VERSION 3.15)
     cmake_policy(SET CMP0091 NEW)
     set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
-    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
-    if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
-        set(CMAKE_MSVC_RUNTIME_LIBRARY "${CMAKE_MSVC_RUNTIME_LIBRARY}Debug")
-    endif()
-    if(BUILD_SHARED_LIBS)
-        set(CMAKE_MSVC_RUNTIME_LIBRARY "${CMAKE_MSVC_RUNTIME_LIBRARY}DLL")
-    endif()
-    message(STATUS "CMAKE_MSVC_RUNTIME_LIBRARY=${CMAKE_MSVC_RUNTIME_LIBRARY}")
 ENDIF()
 
 ###########################################
@@ -177,11 +169,16 @@ if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
 
         $<INSTALL_INTERFACE:include>
     )
+
+    set_target_properties(caosdb_grpc PROPERTIES
+        COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
 else()
     add_library(caosdb
         ${libcaosdb_INCL} ${libcaosdb_SRC} ${GRPC_GENERATED})
     set(LIBCAOSDB caosdb)
 endif()
+
+set(TARGET_CAOSDB_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
 target_link_libraries(caosdb
     ${CONAN_LIBS}
 )
@@ -194,30 +191,21 @@ target_include_directories(caosdb PUBLIC
     $<INSTALL_INTERFACE:include>
 )
 
+###################################################
+# ccaosdb - A C-Wrapper of the C++ caosdb library
+###################################################
 add_library(ccaosdb SHARED src/ccaosdb.cpp)
-IF (WIN32)
-    set_target_properties(caosdb PROPERTIES
-        LINK_FLAGS "/WHOLEARCHIVE"
-    )
-    target_link_libraries(ccaosdb
-        ${LIBCAOSDB}
-        ${CONAN_LIBS}
-    )
-ELSE()
-    set_target_properties(caosdb PROPERTIES
-        COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
     target_link_libraries(ccaosdb
         "-Wl,--whole-archive"
         ${LIBCAOSDB}
         "-Wl,--no-whole-archive"
-        ${CONAN_LIBS}
     )
-ENDIF()
 
+######################################
+# ccaosdbcli - A plain C test client.
+######################################
 add_executable(ccaosdbcli EXCLUDE_FROM_ALL src/ccaosdbcli.c)
-target_include_directories(ccaosdbcli SYSTEM PUBLIC
-    ${CONAN_INCLUDE_DIRS}
-)
+
 target_include_directories(ccaosdbcli PUBLIC
     $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include>
     $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include>
@@ -228,6 +216,10 @@ target_link_libraries(ccaosdbcli
     ${CONAN_LIBS}
 )
 
+######################################
+# cxxcaosdbcli - A C++ test client.
+######################################
+
 add_executable(cxxcaosdbcli EXCLUDE_FROM_ALL src/cxxcaosdbcli.cpp)
 target_include_directories(cxxcaosdbcli SYSTEM PUBLIC
     ${CONAN_INCLUDE_DIRS}
diff --git a/include/ccaosdb.h b/include/ccaosdb.h
index 4d1b99d..ad6bafe 100644
--- a/include/ccaosdb.h
+++ b/include/ccaosdb.h
@@ -20,10 +20,12 @@
  *
  */
 
-#include <cstdint> // for int64_t
-
 #ifdef __cplusplus
+#include <cstdint> // for int64_t
 extern "C" {
+#else
+#include <stdint.h>  // for int64_t
+#include <stdbool.h> // for bool
 #endif
 
 /**
@@ -70,7 +72,7 @@ int caosdb_status_code_OTHER_CLIENT_ERROR();
  */
 typedef struct caosdb_connection_connection {
   void *wrapped_connection;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_connection_connection;
 
 /**
@@ -82,7 +84,7 @@ typedef struct caosdb_connection_connection {
  */
 typedef struct caosdb_connection_connection_configuration {
   void *wrapped_connection_configuration;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_connection_connection_configuration;
 
 /**
@@ -102,12 +104,12 @@ typedef struct caosdb_info_version_info {
 
 typedef struct caosdb_connection_certificate_provider {
   void *wrapped_certificate_provider;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_connection_certificate_provider;
 
 typedef struct caosdb_authentication_authenticator {
   void *wrapped_authenticator;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_authentication_authenticator;
 
 /**
@@ -266,7 +268,7 @@ int caosdb_connection_connection_manager_get_connection(caosdb_connection_connec
 
 typedef struct caosdb_transaction_transaction {
   void *wrapped_transaction;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_transaction_transaction;
 
 /**
@@ -292,12 +294,12 @@ int caosdb_transaction_transaction_execute(caosdb_transaction_transaction *trans
 
 typedef struct caosdb_transaction_result_set {
   void *wrapped_result_set;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_transaction_result_set;
 
 typedef struct caosdb_entity_entity {
   void *wrapped_entity;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_entity_entity;
 
 int caosdb_transaction_transaction_get_result_set(caosdb_transaction_transaction *transaction,
@@ -348,27 +350,27 @@ int caosdb_transaction_transaction_delete_by_id(caosdb_transaction_transaction *
 
 typedef struct caosdb_entity_property {
   void *wrapped_property;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_entity_property;
 
 typedef struct caosdb_entity_parent {
   void *wrapped_parent;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_entity_parent;
 
 typedef struct caosdb_entity_message {
   void *wrapped_message;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_entity_message;
 
 typedef struct caosdb_entity_value {
   void *wrapped_value;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_entity_value;
 
 typedef struct caosdb_entity_datatype {
   void *wrapped_datatype;
-  bool _deletable = false;
+  bool _deletable;
 } caosdb_entity_datatype;
 
 // GETTERS FOR EVERYTHING
diff --git a/src/caosdb/authentication.cpp b/src/caosdb/authentication.cpp
index 50ff244..ecfbe35 100644
--- a/src/caosdb/authentication.cpp
+++ b/src/caosdb/authentication.cpp
@@ -19,13 +19,15 @@
  *
  */
 #include "caosdb/authentication.h"
-#include "grpcpp/security/credentials.h"    // for MetadataCredentialsPlugin
-#include <grpcpp/impl/codegen/status.h>     // for Status, Status::OK
-#include <grpcpp/impl/codegen/string_ref.h> // for string_ref
-#include <map>                              // for multimap
-#include <memory>                           // for allocator, shared_ptr
-#include <string>                           // for basic_string, operator+
-#include <utility>                          // for pair, move, make_pair
+#include <grpcpp/impl/codegen/interceptor.h>           // for Status
+#include <grpcpp/impl/codegen/security/auth_context.h> // for AuthContext
+#include <grpcpp/impl/codegen/status.h>                // for Status, Status::OK
+#include <grpcpp/impl/codegen/string_ref.h>            // for string_ref
+#include <grpcpp/security/credentials.h>               // for MetadataCredentialsPlugin
+#include <map>                                         // for multimap
+#include <memory>                                      // for allocator, shared_ptr
+#include <string>                                      // for basic_string, operator+
+#include <utility>                                     // for pair, move, make_pair
 
 namespace caosdb::authentication {
 using caosdb::utility::base64_encode;
diff --git a/src/ccaosdb.cpp b/src/ccaosdb.cpp
index d33d74e..6558480 100644
--- a/src/ccaosdb.cpp
+++ b/src/ccaosdb.cpp
@@ -58,8 +58,8 @@ extern "C" {
 #define ENUM_VALUE_FROM_NAME(arg, etype)                                                           \
   caosdb::utility::getEnumValueFromName<caosdb::entity::etype>(arg)
 
-#define RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(name)                                                \
-  if (name->_deletable) {                                                                          \
+#define RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(arg)                                                  \
+  if (arg) {                                                                                       \
     return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;                                          \
   }
 
@@ -163,7 +163,7 @@ extern "C" {
 #define CREATE_VALUE(fname, arg)                                                                   \
   ERROR_RETURN_CODE(GENERIC_ERROR,                                                                 \
                     int caosdb_entity_create_##fname(caosdb_entity_value *out, arg), {             \
-                      RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)                                   \
+                      RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_value)                     \
                       out->wrapped_value = new caosdb::entity::Value(value);                       \
                       out->_deletable = true;                                                      \
                       return 0;                                                                    \
@@ -175,7 +175,7 @@ extern "C" {
   ERROR_RETURN_CODE(                                                                               \
     GENERIC_ERROR,                                                                                 \
     int caosdb_entity_create_##fname(caosdb_entity_value *out, arg, const int length), {           \
-      if (out->_deletable) {                                                                       \
+      if (out->wrapped_value) {                                                                    \
         return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;                                      \
       }                                                                                            \
       std::vector<type> value_vec;                                                                 \
@@ -245,7 +245,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_create_pem_file_certificate_provider(
                     caosdb_connection_certificate_provider *out, const char *path),
                   {
-                    if (out->_deletable) {
+                    if (out->wrapped_certificate_provider) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_certificate_provider =
@@ -258,10 +258,11 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_delete_certificate_provider(
                     caosdb_connection_certificate_provider *provider),
                   {
-                    if (provider->_deletable) {
+                    if (provider->_deletable && provider->wrapped_certificate_provider) {
                       delete static_cast<caosdb::configuration::CertificateProvider *>(
                         provider->wrapped_certificate_provider);
                     }
+                    provider->wrapped_certificate_provider = nullptr;
                     provider->_deletable = false;
                     return 0;
                   })
@@ -271,7 +272,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                     caosdb_authentication_authenticator *out, const char *username,
                     const char *password),
                   {
-                    if (out->_deletable) {
+                    if (out->wrapped_authenticator) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_authenticator =
@@ -285,10 +286,11 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_authentication_delete_authenticator(
                     caosdb_authentication_authenticator *authenticator),
                   {
-                    if (authenticator->_deletable) {
+                    if (authenticator->_deletable && authenticator->wrapped_authenticator) {
                       delete static_cast<caosdb::authentication::Authenticator *>(
                         authenticator->wrapped_authenticator);
                     }
+                    authenticator->wrapped_authenticator = nullptr;
                     authenticator->_deletable = false;
                     return 0;
                   })
@@ -300,9 +302,7 @@ ERROR_RETURN_CODE(
     caosdb_authentication_authenticator *authenticator,
     caosdb_connection_certificate_provider *provider),
   {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
+    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_connection_configuration)
     auto host_str = std::string(host);
     if (authenticator != nullptr && provider != nullptr) {
       auto wrapped_provider = static_cast<caosdb::configuration::CertificateProvider *>(
@@ -334,7 +334,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                     caosdb_connection_connection_configuration *out, const char *host,
                     const int port),
                   {
-                    if (out->_deletable) {
+                    if (out->wrapped_connection_configuration) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_connection_configuration =
@@ -347,10 +347,12 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_delete_connection_configuration(
                     caosdb_connection_connection_configuration *configuration),
                   {
-                    if (configuration->_deletable) {
+                    if (configuration->_deletable &&
+                        configuration->wrapped_connection_configuration) {
                       delete static_cast<caosdb::configuration::ConnectionConfiguration *>(
                         configuration->wrapped_connection_configuration);
                     }
+                    configuration->wrapped_connection_configuration = nullptr;
                     configuration->_deletable = false;
                     return 0;
                   })
@@ -360,7 +362,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                     caosdb_connection_connection *out,
                     const caosdb_connection_connection_configuration *configuration),
                   {
-                    if (out->_deletable) {
+                    if (out->wrapped_connection) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     caosdb::configuration::ConnectionConfiguration *config =
@@ -374,10 +376,11 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_delete_connection(caosdb_connection_connection *connection),
                   {
-                    if (connection->_deletable) {
+                    if (connection->_deletable && connection->wrapped_connection) {
                       delete static_cast<caosdb::connection::Connection *>(
                         connection->wrapped_connection);
                     }
+                    connection->wrapped_connection = nullptr;
                     connection->_deletable = false;
                     return 0;
                   })
@@ -417,7 +420,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_connection_manager_get_default_connection(
                     caosdb_connection_connection *out),
                   {
-                    if (out->_deletable) {
+                    if (out->wrapped_connection) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_connection =
@@ -430,7 +433,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_connection_manager_get_connection(
                     caosdb_connection_connection *out, const char *name),
                   {
-                    if (out->_deletable) {
+                    if (out->wrapped_connection) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_connection =
@@ -448,9 +451,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_connection_create_transaction(
                     caosdb_connection_connection *connection, caosdb_transaction_transaction *out),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_transaction)
                     auto *wrapped_connection =
                       static_cast<caosdb::connection::Connection *>(connection->wrapped_connection);
                     out->wrapped_transaction = wrapped_connection->CreateTransaction().release();
@@ -461,9 +462,11 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
 ERROR_RETURN_CODE(
   GENERIC_ERROR,
   int caosdb_transaction_delete_transaction(caosdb_transaction_transaction *transaction), {
-    if (transaction->_deletable) {
+    if (transaction->_deletable && transaction->wrapped_transaction) {
       delete static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction);
     }
+    transaction->wrapped_transaction = nullptr;
+    transaction->_deletable = false;
     return 0;
   })
 
@@ -553,9 +556,7 @@ ERROR_RETURN_CODE(
   int caosdb_transaction_transaction_get_result_set(caosdb_transaction_transaction *transaction,
                                                     caosdb_transaction_result_set *out),
   {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
+    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_result_set)
     auto *wrapped_transaction =
       static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction);
     out->wrapped_result_set = (void *)(&(wrapped_transaction->GetResultSet()));
@@ -568,7 +569,7 @@ ERROR_RETURN_CODE(
   int caosdb_transaction_transaction_release_result_set(caosdb_transaction_transaction *transaction,
                                                         caosdb_transaction_result_set *out),
   {
-    if (out->_deletable) {
+    if (out->wrapped_result_set) {
       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
     }
     auto *wrapped_transaction =
@@ -582,9 +583,10 @@ ERROR_RETURN_CODE(
 ERROR_RETURN_CODE(
   GENERIC_ERROR,
   int caosdb_transaction_delete_result_set(caosdb_transaction_result_set *result_set), {
-    if (result_set->_deletable) {
+    if (result_set->_deletable && result_set->wrapped_result_set) {
       delete static_cast<caosdb::entity::Entity *>(result_set->wrapped_result_set);
     }
+    result_set->wrapped_result_set = nullptr;
     result_set->_deletable = false;
     return 0;
   })
@@ -615,7 +617,7 @@ ERROR_RETURN_CODE(
   int caosdb_transaction_result_set_release_at(caosdb_transaction_result_set *result_set,
                                                caosdb_entity_entity *entity, int index),
   {
-    if (entity->_deletable) {
+    if (entity->wrapped_entity) {
       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
     }
     auto *wrapped_result_set =
@@ -638,7 +640,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_entity(caosdb_entity_entity *out), {
-  if (out->_deletable) {
+  if (out->wrapped_entity) {
     return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
   }
   out->wrapped_entity = new caosdb::entity::Entity();
@@ -647,15 +649,16 @@ ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_entity(caosdb_entity_e
 })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_entity(caosdb_entity_entity *out), {
-  if (out->_deletable) {
+  if (out->_deletable && out->wrapped_entity) {
     delete static_cast<caosdb::entity::Entity *>(out->wrapped_entity);
   }
+  out->wrapped_entity = nullptr;
   out->_deletable = false;
   return 0;
 })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_property(caosdb_entity_property *out), {
-  if (out->_deletable) {
+  if (out->wrapped_property) {
     return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
   }
   out->wrapped_property = new caosdb::entity::Property();
@@ -664,15 +667,16 @@ ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_property(caosdb_entity
 })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_property(caosdb_entity_property *out), {
-  if (out->_deletable) {
+  if (out->_deletable && out->wrapped_property) {
     delete static_cast<caosdb::entity::Property *>(out->wrapped_property);
   }
+  out->wrapped_property = nullptr;
   out->_deletable = false;
   return 0;
 })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_parent(caosdb_entity_parent *out), {
-  if (out->_deletable) {
+  if (out->wrapped_parent) {
     return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
   }
   out->wrapped_parent = new caosdb::entity::Parent();
@@ -681,9 +685,10 @@ ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_parent(caosdb_entity_p
 })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_parent(caosdb_entity_parent *out), {
-  if (out->_deletable) {
+  if (out->_deletable && out->wrapped_parent) {
     delete static_cast<caosdb::entity::Parent *>(out->wrapped_parent);
   }
+  out->wrapped_parent = nullptr;
   out->_deletable = false;
   return 0;
 })
@@ -692,7 +697,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_create_atomic_datatype(caosdb_entity_datatype *out,
                                                            const char *name),
                   {
-                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_datatype)
                     try {
                       auto enum_value = ENUM_VALUE_FROM_NAME(std::string(name), AtomicDataType);
                       out->wrapped_datatype = new caosdb::entity::DataType(enum_value);
@@ -707,7 +712,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_create_reference_datatype(caosdb_entity_datatype *out,
                                                               const char *name),
                   {
-                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_datatype)
                     out->wrapped_datatype = new caosdb::entity::DataType(std::string(name));
                     out->_deletable = true;
                     return 0;
@@ -716,7 +721,7 @@ 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)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_datatype)
                     try {
                       auto enum_value = ENUM_VALUE_FROM_NAME(std::string(name), AtomicDataType);
                       out->wrapped_datatype =
@@ -732,7 +737,7 @@ 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)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_datatype)
                     out->wrapped_datatype = new caosdb::entity::DataType(
                       caosdb::entity::DataType::ListOf(std::string(name)));
                     out->_deletable = true;
@@ -740,9 +745,10 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_datatype(caosdb_entity_datatype *out), {
-  if (out->_deletable) {
+  if (out->_deletable && out->wrapped_datatype) {
     delete WRAPPED_DATATYPE_CAST(out);
   }
+  out->wrapped_datatype = nullptr;
   out->_deletable = false;
   return 0;
 })
@@ -757,9 +763,10 @@ CREATE_VECTOR_VALUE(double_vector_value, double, const double *value, value[i])
 CREATE_VECTOR_VALUE(bool_vector_value, bool, const bool *value, value[i])
 
 ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_value(caosdb_entity_value *out), {
-  if (out->_deletable) {
+  if (out->_deletable && out->wrapped_value) {
     delete WRAPPED_VALUE_CAST(out);
   }
+  out->wrapped_value = nullptr;
   out->_deletable = false;
   return 0;
 })
@@ -793,7 +800,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity,
                                                         caosdb_entity_datatype *out),
                   {
-                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_datatype)
                     auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity);
                     out->wrapped_datatype = (void *)(&(wrapped_entity->GetDataType()));
                     out->_deletable = false;
@@ -803,7 +810,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_value(caosdb_entity_entity *entity,
                                                      caosdb_entity_value *out),
                   {
-                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_value)
                     auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity);
                     out->wrapped_value = (void *)(&(wrapped_entity->GetValue()));
                     out->_deletable = false;
@@ -826,9 +833,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_error(caosdb_entity_entity *entity,
                                                      caosdb_entity_message *out, int index),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_message)
                     auto *wrapped_entity =
                       static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
                     out->wrapped_message = wrapped_entity->GetErrors().mutable_at(index);
@@ -850,9 +855,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_warning(caosdb_entity_entity *entity,
                                                        caosdb_entity_message *out, int index),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_message)
                     auto *wrapped_entity =
                       static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
                     out->wrapped_message = wrapped_entity->GetWarnings().mutable_at(index);
@@ -872,9 +875,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_info(caosdb_entity_entity *entity,
                                                     caosdb_entity_message *out, int index),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_message)
                     auto *wrapped_entity =
                       static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
                     out->wrapped_message = wrapped_entity->GetInfos().mutable_at(index);
@@ -896,9 +897,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_property(caosdb_entity_entity *entity,
                                                         caosdb_entity_property *out, int index),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_property)
                     auto *wrapped_entity =
                       static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
                     out->wrapped_property = wrapped_entity->GetProperties().mutable_at(index);
@@ -919,9 +918,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_entity_get_parent(caosdb_entity_entity *entity,
                                                       caosdb_entity_parent *out, int index),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_parent)
                     auto *wrapped_entity =
                       static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
                     out->wrapped_parent = wrapped_entity->GetParents().mutable_at(index);
@@ -954,7 +951,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_property_get_datatype(caosdb_entity_property *property,
                                                           caosdb_entity_datatype *out),
                   {
-                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_datatype)
                     auto *wrapped_property = WRAPPED_PROPERTY_CAST(property);
                     out->wrapped_datatype = (void *)(&(wrapped_property->GetDataType()));
                     out->_deletable = false;
@@ -964,7 +961,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_entity_property_get_value(caosdb_entity_property *property,
                                                        caosdb_entity_value *out),
                   {
-                    RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out)
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_value)
                     auto *wrapped_property = WRAPPED_PROPERTY_CAST(property);
                     out->wrapped_value = (void *)(&(wrapped_property->GetValue()));
                     out->_deletable = false;
@@ -1092,9 +1089,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                                                            caosdb_entity_value *out,
                                                            const int index),
                   {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
+                    RETURN_ASSIGNEMENT_ERROR_IF_NON_NULL(out->wrapped_value)
                     auto *wrapped_value = WRAPPED_VALUE_CAST(value);
                     out->wrapped_value = (void *)(&(wrapped_value->GetAsVector().at(index)));
                     out->_deletable = false;
diff --git a/src/cxxcaosdbcli.cpp b/src/cxxcaosdbcli.cpp
index bb60696..c0c4234 100644
--- a/src/cxxcaosdbcli.cpp
+++ b/src/cxxcaosdbcli.cpp
@@ -53,24 +53,14 @@ auto main() -> int {
 
     // retrieve an entity
     auto transaction(connection->CreateTransaction());
-    transaction->RetrieveById("120");
+    transaction->RetrieveById("21");
     transaction->ExecuteAsynchronously();
     auto t_stat = transaction->WaitForIt();
     CAOSDB_LOG_INFO(logger_name) << "status: " << t_stat.GetCode() << " // "
                                  << t_stat.GetDescription();
     const auto &result_set = transaction->GetResultSet();
-    if (result_set.size() > 0) {
-      // print information
-      const auto &ent = result_set.at(0);
-      const auto &props = ent.GetProperties();
-      std::cout << "Entity Name: " << ent.GetName() << std::endl;
-      std::cout << "Entity Description: " << ent.GetDescription() << std::endl;
-      std::cout << "Entity Properties: " << std::endl;
-      for (const auto &prop : props) {
-        std::cout << "----------\n" << prop.ToString() << std::endl;
-      }
-    } else {
-      std::cout << "No entity \"120\" retrieved, maybe it does not exist?\n" << std::endl;
+    for (const auto &entity : result_set) {
+      std::cout << entity.ToString() << std::endl;
     }
 
     // execute a query
@@ -82,6 +72,11 @@ auto main() -> int {
     t_stat = q_transaction->WaitForIt();
     CAOSDB_LOG_INFO(logger_name) << "status: " << t_stat.GetCode() << " // "
                                  << t_stat.GetDescription();
+    const auto &result_set_2 = q_transaction->GetResultSet();
+    for (const auto &entity : result_set_2) {
+      std::cout << entity.ToString() << std::endl;
+    }
+
     return 0;
   } catch (const caosdb::exceptions::ConfigurationError &exc) {
     std::cout << "ConfigurationError: " << exc.what() << std::endl;
-- 
GitLab