diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 49579705b8acdc8faf7d2ac232a6c1dc9faa08fa..cced2f686368c9f34dae1884140d53958a7e267e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -89,10 +89,10 @@ test: - echo "FILE_TO_BE_PATCHED=$FILE_TO_BE_PATCHED" - sed -e "s|std::unique_ptr<ContextAllocator> context_allocator) {}|std::unique_ptr<ContextAllocator> /*context_allocator*/) {}|" -i $FILE_TO_BE_PATCHED - cmake -DCMAKE_BUILD_TYPE=Debug .. - - cmake --build . - - cmake --build . --target unit_test_coverage - - cmake --build . --target cxxcaosdbcli - - cmake --build . --target ccaosdbcli + - cmake --build . -j + - cmake --build . -j --target unit_test_coverage + - cmake --build . -j --target cxxcaosdbcli + - cmake --build . -j --target ccaosdbcli # trigger the integration tests trigger_inttest: diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d39bda064d6caf53ddfd816cdb398f1eed07de..aa0ef42ba87dcf92bc82690d837609b5e4a12b67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * New functions getEnumNameFromValue() and getEnumValueFromName(). -* Extern C now supports datatypes, roles, and importances as enums, - and typed property values +* Extern C now supports the full C++ functionalities. ### Changed diff --git a/doc/Examples.rst b/doc/Examples.rst index ea65e02cd421b880d5d748c6774798ac115d0d9a..ddb24e0bdd6fd7a4f4881a8eb163cb63184b0bb8 100644 --- a/doc/Examples.rst +++ b/doc/Examples.rst @@ -224,11 +224,11 @@ Up- and Download a file const auto &insert_results = insert_transaction->GetResultSet(); const auto &inserted_file = insert_results.at(0); - // for the download you need to use the RetrieveAndDownloadFilesById task and + // for the download you need to use the RetrieveAndDownloadFileById task and // supply the path where the file shall be stored test_download_file = fs::path("test_download_file_delete_me.dat"); auto download_transaction(connection->CreateTransaction()); - download_transaction->RetrieveAndDownloadFilesById( + download_transaction->RetrieveAndDownloadFileById( inserted_file.GetId(), test_download_file.string()); download_transaction->ExecuteAsynchronously(); download_transaction->WaitForIt().GetCode() diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h index 0fb724a5316e6f615d4236aa24dc44d338fce803..621c6cbd80057c0f97d171f2ffac91e65b77498f 100644 --- a/include/caosdb/transaction.h +++ b/include/caosdb/transaction.h @@ -279,7 +279,7 @@ public: * If the file cannot be downloaded due to unsufficient permissions an error * is appended. */ - auto RetrieveAndDownloadFilesById(const std::string &id, const std::string &local_path) noexcept + auto RetrieveAndDownloadFileById(const std::string &id, const std::string &local_path) noexcept -> StatusCode; /** diff --git a/include/ccaosdb.h b/include/ccaosdb.h index e23e3a72ad58167e060081757e97d84cbfeaa2b8..b06f3ec388d14a2b15b362babd99e3207a7353ef 100644 --- a/include/ccaosdb.h +++ b/include/ccaosdb.h @@ -279,6 +279,8 @@ int caosdb_connection_connection_create_transaction(caosdb_connection_connection int caosdb_transaction_delete_transaction(caosdb_transaction_transaction *transaction); int caosdb_transaction_transaction_retrieve_by_id(caosdb_transaction_transaction *transaction, const char *id); +int caosdb_transaction_transaction_retrieve_and_download_file_by_id( + caosdb_transaction_transaction *transaction, const char *id, const char *path); int caosdb_transaction_transaction_retrieve_by_ids(caosdb_transaction_transaction *transaction, const char *ids[], int length); int caosdb_transaction_transaction_query(caosdb_transaction_transaction *transaction, @@ -307,6 +309,13 @@ int caosdb_transaction_result_set_at(caosdb_transaction_result_set *result_set, caosdb_entity_entity *entity, int index); int caosdb_transaction_result_set_size(caosdb_transaction_result_set *result_set, int *out); +int caosdb_transaction_transaction_insert_entity(caosdb_transaction_transaction *transaction, + caosdb_entity_entity *entity); +int caosdb_transaction_transaction_update_entity(caosdb_transaction_transaction *transaction, + caosdb_entity_entity *entity); +int caosdb_transaction_transaction_delete_by_id(caosdb_transaction_transaction *transaction, + const char *id); + typedef struct { void *wrapped_property; bool _deletable = false; @@ -325,6 +334,7 @@ int caosdb_entity_entity_get_id(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_role(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_name(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_description(caosdb_entity_entity *entity, char **out); +int caosdb_entity_entity_get_local_path(caosdb_entity_entity *entity, char **out); /** * Get the name of the entity's datatype, whether it is a reference, and whether it is a list. */ @@ -407,6 +417,8 @@ int caosdb_entity_delete_parent(caosdb_entity_parent *out); int caosdb_entity_entity_set_role(caosdb_entity_entity *entity, const char *role); int caosdb_entity_entity_set_name(caosdb_entity_entity *entity, const char *name); int caosdb_entity_entity_set_description(caosdb_entity_entity *entity, const char *description); +int caosdb_entity_entity_set_local_path(caosdb_entity_entity *entity, const char *name); +int caosdb_entity_entity_set_file_path(caosdb_entity_entity *entity, const char *name); /** * Set the entity's datatype by name, and whether it is a reference or a list. */ diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index 5a7cb74683071f42e54f8ad056f37643092bb4ef..58bf54e92554f4660293a869954e9e3482eebdf7 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -172,8 +172,8 @@ auto Transaction::RetrieveById(const std::string &id) noexcept -> StatusCode { return this->status.GetCode(); } -auto Transaction::RetrieveAndDownloadFilesById(const std::string &id, - const std::string &local_path) noexcept +auto Transaction::RetrieveAndDownloadFileById(const std::string &id, + const std::string &local_path) noexcept -> StatusCode { ASSERT_CAN_ADD_RETRIEVAL diff --git a/src/ccaosdb.cpp b/src/ccaosdb.cpp index 40a47227c5d146a97583e5068b033896e17b1cfe..d5165c98e64b7084a395a710a5bd1b98019f9edb 100644 --- a/src/ccaosdb.cpp +++ b/src/ccaosdb.cpp @@ -75,7 +75,7 @@ extern "C" { GENERIC_ERROR, \ int caosdb_entity_entity_get_##element(caosdb_entity_entity *entity, char **out), { \ auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); \ - char *tmp = (char *)malloc(sizeof(char) * wrapped_entity->GetFunction.length() + 1); \ + auto *tmp = (char *)malloc(sizeof(char) * wrapped_entity->GetFunction.length() + 1); \ strcpy(tmp, wrapped_entity->GetFunction.c_str()); \ delete[] * out; \ *out = tmp; \ @@ -101,7 +101,7 @@ extern "C" { GENERIC_ERROR, \ int caosdb_entity_property_get_##element(caosdb_entity_property *property, char **out), { \ auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); \ - char *tmp = (char *)malloc(sizeof(char) * wrapped_property->GetFunction.length() + 1); \ + auto *tmp = (char *)malloc(sizeof(char) * wrapped_property->GetFunction.length() + 1); \ strcpy(tmp, wrapped_property->GetFunction.c_str()); \ delete[] * out; \ *out = tmp; \ @@ -128,7 +128,7 @@ extern "C" { GENERIC_ERROR, \ int caosdb_entity_parent_get_##element(caosdb_entity_parent *parent, char **out), { \ auto *wrapped_parent = WRAPPED_PARENT_CAST(parent); \ - char *tmp = (char *)malloc(sizeof(char) * wrapped_parent->GetFunction.length() + 1); \ + auto *tmp = (char *)malloc(sizeof(char) * wrapped_parent->GetFunction.length() + 1); \ strcpy(tmp, wrapped_parent->GetFunction.c_str()); \ delete[] * out; \ *out = tmp; \ @@ -338,12 +338,12 @@ ERROR_RETURN_CODE( out->patch = (int)version_info->GetPatch(); // copy pre_release, needs local variable because out->pre_release is const - char *pre_release = (char *)malloc(sizeof(char) * (version_info->GetPreRelease().length() + 1)); + auto *pre_release = (char *)malloc(sizeof(char) * (version_info->GetPreRelease().length() + 1)); strcpy(pre_release, version_info->GetPreRelease().c_str()); out->pre_release = pre_release; // copy build, needs local variable because out->build is const - char *build = (char *)malloc(sizeof(char) * (version_info->GetBuild().length() + 1)); + auto *build = (char *)malloc(sizeof(char) * (version_info->GetBuild().length() + 1)); strcpy(build, version_info->GetBuild().c_str()); out->build = build; @@ -413,6 +413,16 @@ ERROR_RETURN_CODE(GENERIC_ERROR, return wrapped_transaction->RetrieveById(std::string(id)); }) +ERROR_RETURN_CODE(GENERIC_ERROR, + int caosdb_transaction_transaction_retrieve_and_download_file_by_id( + caosdb_transaction_transaction *transaction, const char *id, const char *path), + { + auto *wrapped_transaction = static_cast<caosdb::transaction::Transaction *>( + transaction->wrapped_transaction); + return wrapped_transaction->RetrieveAndDownloadFileById(std::string(id), + std::string(path)); + }) + ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_transaction_transaction_retrieve_by_ids( caosdb_transaction_transaction *transaction, const char *ids[], int length), @@ -431,6 +441,40 @@ ERROR_RETURN_CODE(GENERIC_ERROR, return wrapped_transaction->Query(std::string(query)); }) +ERROR_RETURN_CODE( + GENERIC_ERROR, + int caosdb_transaction_transaction_insert_entity(caosdb_transaction_transaction *transaction, + caosdb_entity_entity *entity), + { + auto *wrapped_transaction = + static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction); + auto *wrapped_entity = static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); + + return wrapped_transaction->InsertEntity(wrapped_entity); + }) + +ERROR_RETURN_CODE( + GENERIC_ERROR, + int caosdb_transaction_transaction_update_entity(caosdb_transaction_transaction *transaction, + caosdb_entity_entity *entity), + { + auto *wrapped_transaction = + static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction); + auto *wrapped_entity = static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); + + return wrapped_transaction->UpdateEntity(wrapped_entity); + }) + +ERROR_RETURN_CODE(GENERIC_ERROR, + int caosdb_transaction_transaction_delete_by_id( + caosdb_transaction_transaction *transaction, const char *id), + { + auto *wrapped_transaction = static_cast<caosdb::transaction::Transaction *>( + transaction->wrapped_transaction); + + return wrapped_transaction->DeleteById(std::string(id)); + }) + ERROR_RETURN_CODE( GENERIC_ERROR, int caosdb_transaction_transaction_execute(caosdb_transaction_transaction *transaction), { @@ -544,13 +588,25 @@ ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_entity_get_role(caosdb_entity_entity *entity, char **out), { auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); std::string role_str = ENUM_NAME_FROM_VALUE(wrapped_entity->GetRole(), Role); - char *tmp = (char *)malloc(sizeof(char) * role_str.length() + 1); + auto *tmp = (char *)malloc(sizeof(char) * role_str.length() + 1); strcpy(tmp, role_str.c_str()); delete[] * out; *out = tmp; return 0; }) CAOSDB_ENTITY_GET(name, GetName()) +ERROR_RETURN_CODE(GENERIC_ERROR, + int caosdb_entity_entity_get_local_path(caosdb_entity_entity *entity, char **out), + { + auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); + auto path = wrapped_entity->GetLocalPath().string(); + auto *tmp = (char *)(malloc(sizeof(char) * path.length() + 1)); + strcpy(tmp, path.c_str()); + delete[] * out; + *out = tmp; + return 0; + }) +// CAOSDB_ENTITY_GET(file_path, GetFilePath()) TODO(henrik) CAOSDB_ENTITY_GET(description, GetDescription()) ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity, char **name, @@ -895,7 +951,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR, { auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); auto value_list = wrapped_property->GetValue().AsList(); - char *tmp = + auto *tmp = (char *)malloc(sizeof(char) * value_list[index].AsString().length() + 1); strcpy(tmp, value_list[index].AsString().c_str()); delete[] * out; @@ -928,7 +984,7 @@ ERROR_RETURN_CODE( GENERIC_ERROR, int caosdb_entity_message_get_description(caosdb_entity_message *message, char **out), { auto *wrapped_message = static_cast<caosdb::entity::Message *>(message->wrapped_message); - char *tmp = (char *)malloc(sizeof(char) * wrapped_message->GetDescription().length() + 1); + auto *tmp = (char *)malloc(sizeof(char) * wrapped_message->GetDescription().length() + 1); strcpy(tmp, wrapped_message->GetDescription().c_str()); delete[] * out; *out = tmp; @@ -949,6 +1005,9 @@ ERROR_RETURN_CODE(GENERIC_ERROR, } }) CAOSDB_ENTITY_SET(name, name, wrapped_entity->SetName(std::string(name));) +CAOSDB_ENTITY_SET(local_path, local_path, + return wrapped_entity->SetLocalPath(boost::filesystem::path(local_path));) +CAOSDB_ENTITY_SET(file_path, file_path, wrapped_entity->SetFilePath(std::string(file_path));) CAOSDB_ENTITY_SET(description, description, wrapped_entity->SetDescription(std::string(description));) ERROR_RETURN_CODE(GENERIC_ERROR, diff --git a/test/test_ccaosdb.cpp b/test/test_ccaosdb.cpp index c68d4ef14df142fcb6e8d75df51c89cf59cb0101..fe9142862b1b4da10f23db06a2a20abe529ae35a 100644 --- a/test/test_ccaosdb.cpp +++ b/test/test_ccaosdb.cpp @@ -152,6 +152,16 @@ TEST_F(test_ccaosdb, test_entity) { EXPECT_EQ(return_code, 0); EXPECT_EQ(strcmp(out, "length"), 0); + // test call without validation of result + return_code = caosdb_entity_entity_set_role(&entity, "FILE"); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_entity_set_local_path( + &entity, (TEST_DATA_DIR + "/test_caosdb_client.json").c_str()); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_entity_get_local_path(&entity, &out); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(strcmp(out, (TEST_DATA_DIR + "/test_caosdb_client.json").c_str()), 0); + // invalid role return_code = caosdb_entity_entity_set_role(&entity, "Role does not exist"); EXPECT_EQ(return_code, caosdb::StatusCode::ENUM_MAPPING_ERROR); @@ -453,3 +463,42 @@ TEST_F(test_ccaosdb, test_remove_property) { return_code = caosdb_entity_delete_entity(&entity); EXPECT_EQ(return_code, 0); } + +TEST_F(test_ccaosdb, test_insert_update_delete) { + // Only test adding to a transaction. Excution and results are + // tested in integration tests. + caosdb_connection_connection connection; + caosdb_connection_connection_manager_get_default_connection(&connection); + + caosdb_transaction_transaction insert_transaction; + caosdb_connection_connection_create_transaction(&connection, &insert_transaction); + + caosdb_entity_entity entity; + caosdb_entity_create_entity(&entity); + caosdb_entity_entity_set_name(&entity, "some_name"); + caosdb_entity_entity_set_local_path(&entity, "some_name"); + caosdb_entity_entity_set_file_path(&entity, "some_name"); + + auto return_code = caosdb_transaction_transaction_insert_entity(&insert_transaction, &entity); + // For now, nothing further can be done here, so it should be READY + EXPECT_EQ(return_code, caosdb::StatusCode::READY); + + caosdb_transaction_transaction update_transaction; + caosdb_connection_connection_create_transaction(&connection, &update_transaction); + + return_code = caosdb_transaction_transaction_update_entity(&update_transaction, &entity); + // No ID, so this should be an error + EXPECT_EQ(return_code, caosdb::StatusCode::ORIGINAL_ENTITY_MISSING_ID); + + caosdb_transaction_transaction delete_transaction; + caosdb_connection_connection_create_transaction(&connection, &delete_transaction); + + return_code = caosdb_transaction_transaction_delete_by_id(&delete_transaction, "some_id"); + // Could add further deletions + EXPECT_EQ(return_code, caosdb::StatusCode::GO_ON); + + caosdb_entity_delete_entity(&entity); + caosdb_transaction_delete_transaction(&insert_transaction); + caosdb_transaction_delete_transaction(&update_transaction); + caosdb_transaction_delete_transaction(&delete_transaction); +} diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp index 21c00f86b20758e03dc6f1d78e4aad11b469479e..db2d76a845f5548eb68570d183e1a7867a91fe15 100644 --- a/test/test_transaction.cpp +++ b/test/test_transaction.cpp @@ -199,7 +199,7 @@ TEST(test_transaction, test_retrieve_and_download) { auto transaction = connection.CreateTransaction(); EXPECT_EQ(transaction->GetStatus().GetCode(), StatusCode::INITIAL); - transaction->RetrieveAndDownloadFilesById("asdf", "local_path"); + transaction->RetrieveAndDownloadFileById("asdf", "local_path"); EXPECT_EQ(transaction->GetStatus().GetCode(), StatusCode::GO_ON);