Mercurial > hg > orthanc
changeset 6161:c07e55229823 attach-custom-data
allow custom data to be binary
line wrap: on
line diff
--- a/OrthancFramework/Sources/FileStorage/FileInfo.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancFramework/Sources/FileStorage/FileInfo.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -197,6 +197,19 @@ } + void FileInfo::SwapCustomData(std::string& data) + { + if (valid_) + { + customData_.swap(data); + } + else + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + } + + const std::string& FileInfo::GetCustomData() const { if (valid_)
--- a/OrthancFramework/Sources/FileStorage/FileInfo.h Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancFramework/Sources/FileStorage/FileInfo.h Sat Jun 07 18:50:42 2025 +0200 @@ -87,6 +87,8 @@ void SetCustomData(const std::string& data); + void SwapCustomData(std::string& data); + const std::string& GetCustomData() const; }; }
--- a/OrthancFramework/Sources/SQLite/Statement.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancFramework/Sources/SQLite/Statement.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -249,6 +249,11 @@ } } + void Statement::BindBlob(int col, const std::string& value) + { + BindBlob(col, value.empty() ? NULL : value.c_str(), value.size()); + } + int Statement::ColumnCount() const {
--- a/OrthancFramework/Sources/SQLite/Statement.h Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancFramework/Sources/SQLite/Statement.h Sat Jun 07 18:50:42 2025 +0200 @@ -131,6 +131,7 @@ void BindString(int col, const std::string& val); //void BindString16(int col, const string16& value); void BindBlob(int col, const void* value, size_t value_len); + void BindBlob(int col, const std::string& value); // Retrieving ----------------------------------------------------------------
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -1507,7 +1507,8 @@ } virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) ORTHANC_OVERRIDE + const void* customData, + size_t customDataSize) ORTHANC_OVERRIDE { throw OrthancException(ErrorCode_NotImplemented); // Not supported }
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -1119,7 +1119,8 @@ } virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) ORTHANC_OVERRIDE + const void* customData, + size_t customDataSize) ORTHANC_OVERRIDE { throw OrthancException(ErrorCode_NotImplemented); // Not supported }
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -1055,13 +1055,14 @@ } virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) ORTHANC_OVERRIDE + const void* customData, + size_t customDataSize) ORTHANC_OVERRIDE { if (database_.GetDatabaseCapabilities().HasAttachmentCustomDataSupport()) { DatabasePluginMessages::TransactionRequest request; request.mutable_update_attachment_custom_data()->set_uuid(attachmentUuid); - request.mutable_update_attachment_custom_data()->set_custom_data(customData); + request.mutable_update_attachment_custom_data()->set_custom_data(customData, customDataSize); DatabasePluginMessages::TransactionResponse response; ExecuteTransaction(response, DatabasePluginMessages::OPERATION_UPDATE_ATTACHMENT_CUSTOM_DATA, request);
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -4701,10 +4701,7 @@ void OrthancPlugins::ApplyUpdateAttachmentCustomData(const _OrthancPluginUpdateAttachmentCustomData& parameters) { PImpl::ServerContextReference lock(*pimpl_); - FileInfo fileInfo; - std::string customData(parameters.customData, parameters.customDataSize); - - lock.GetContext().GetIndex().UpdateAttachmentCustomData(parameters.attachmentUuid, customData); + lock.GetContext().GetIndex().UpdateAttachmentCustomData(parameters.attachmentUuid, parameters.customData, parameters.customDataSize); } bool OrthancPlugins::HasKeyValueStoresSupport()
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Sat Jun 07 18:50:42 2025 +0200 @@ -1536,7 +1536,7 @@ OrthancPluginContentType type, uint64_t rangeStart, const void* customData, - uint64_t customDataSize); + uint32_t customDataSize); @@ -1557,7 +1557,7 @@ const char* uuid, OrthancPluginContentType type, const void* customData, - uint64_t customDataSize); + uint32_t customDataSize); /** @@ -9804,7 +9804,7 @@ uint64_t compressedSize; const char* compressedHash; const void* customData; - uint64_t customDataSize; + uint32_t customDataSize; } OrthancPluginAttachment2; @@ -9880,8 +9880,8 @@ typedef struct { const char* attachmentUuid; /* in */ - const char* customData; /* in */ - int64_t customDataSize; /* in */ + const void* customData; /* in */ + uint32_t customDataSize; /* in */ } _OrthancPluginUpdateAttachmentCustomData; @@ -9894,8 +9894,8 @@ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginUpdateAttachmentCustomData( OrthancPluginContext* context, const char* attachmentUuid, /* in */ - const char* customData, /* in */ - int64_t customDataSize /* in */) + const void* customData, /* in */ + uint32_t customDataSize /* in */) { _OrthancPluginUpdateAttachmentCustomData params; params.attachmentUuid = attachmentUuid;
--- a/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Sat Jun 07 18:50:42 2025 +0200 @@ -55,7 +55,7 @@ int32 compression_type = 5; // opaque "CompressionType" in Orthanc uint64 compressed_size = 6; string compressed_hash = 7; - string custom_data = 8; // New in v 1.12.8 + bytes custom_data = 8; // New in 1.12.8 } enum ResourceType { @@ -1090,7 +1090,7 @@ message UpdateAttachmentCustomData { message Request { string uuid = 1; - string custom_data = 2; + bytes custom_data = 2; } message Response {
--- a/OrthancServer/Sources/Database/IDatabaseWrapper.h Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h Sat Jun 07 18:50:42 2025 +0200 @@ -291,7 +291,8 @@ const std::string& attachmentUuid) = 0; virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) = 0; + const void* customData, + size_t customDataSize) = 0; /** * If "shared" is "true", the property is shared by all the
--- a/OrthancServer/Sources/Database/InstallKeyValueStoresAndQueues.sql Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/InstallKeyValueStoresAndQueues.sql Sat Jun 07 18:50:42 2025 +0200 @@ -29,7 +29,7 @@ CREATE TABLE Queues ( id INTEGER PRIMARY KEY AUTOINCREMENT, queueId TEXT NOT NULL, - value BLOB + value BLOB NOT NULL ); CREATE INDEX QueuesIndex ON Queues (queueId, id);
--- a/OrthancServer/Sources/Database/InstallRevisionAndCustomData.sql Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/InstallRevisionAndCustomData.sql Sat Jun 07 18:50:42 2025 +0200 @@ -27,7 +27,7 @@ ALTER TABLE AttachedFiles ADD COLUMN revision INTEGER; -- Add new column for customData -ALTER TABLE AttachedFiles ADD COLUMN customData TEXT; +ALTER TABLE AttachedFiles ADD COLUMN customData BLOB; -- Record that this upgrade has been performed
--- a/OrthancServer/Sources/Database/PrepareDatabase.sql Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/PrepareDatabase.sql Sat Jun 07 18:50:42 2025 +0200 @@ -69,7 +69,7 @@ uncompressedMD5 TEXT, -- New in Orthanc 0.7.3 (database v4) compressedMD5 TEXT, -- New in Orthanc 0.7.3 (database v4) revision INTEGER, -- New in Orthanc 1.12.8 (added in InstallRevisionAndCustomData.sql) - customData TEXT, -- New in Orthanc 1.12.8 (added in InstallRevisionAndCustomData.sql) + customData BLOB, -- New in Orthanc 1.12.8 (added in InstallRevisionAndCustomData.sql) PRIMARY KEY(id, fileType) );
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -427,7 +427,7 @@ s.BindString(6, attachment.GetUncompressedMD5()); s.BindString(7, attachment.GetCompressedMD5()); s.BindInt(8, revision); - s.BindString(9, attachment.GetCustomData()); + s.BindBlob(9, attachment.GetCustomData()); s.Run(); } @@ -1102,7 +1102,13 @@ s.ColumnInt64(C11_BIG_INT_2), s.ColumnString(C4_STRING_2), static_cast<CompressionType>(s.ColumnInt(C8_INT_2)), s.ColumnInt64(C10_BIG_INT_1), s.ColumnString(C5_STRING_3)); - file.SetCustomData(s.ColumnString(C6_STRING_4)); // TODO_ATTACH_CUSTOM_DATA TODO TODO + + std::string customData; + if (s.ColumnBlobAsString(C6_STRING_4, &customData)) + { + file.SwapCustomData(customData); + } + res.AddAttachment(file, s.ColumnInt(C9_INT_3)); }; break; @@ -1262,7 +1268,13 @@ s.ColumnInt64(C11_BIG_INT_2), s.ColumnString(C4_STRING_2), static_cast<CompressionType>(s.ColumnInt(C8_INT_2)), s.ColumnInt64(C10_BIG_INT_1), s.ColumnString(C5_STRING_3)); - file.SetCustomData(s.ColumnString(C6_STRING_4)); // TODO_ATTACH_CUSTOM_DATA TODO TODO + + std::string customData; + if (s.ColumnBlobAsString(C6_STRING_4, &customData)) + { + file.SwapCustomData(customData); + } + res.AddOneInstanceAttachment(file); }; break; @@ -1384,7 +1396,10 @@ if (s.Step()) { - customData = s.ColumnString(0); + if (!s.ColumnBlobAsString(C6_STRING_4, &customData)) + { + customData.clear(); + } } else { @@ -1799,7 +1814,13 @@ static_cast<CompressionType>(s.ColumnInt(2)), s.ColumnInt64(3), s.ColumnString(5)); - attachment.SetCustomData(s.ColumnString(7)); // TODO_ATTACH_CUSTOM_DATA TODO TODO + + std::string customData; + if (s.ColumnBlobAsString(7, &customData)) + { + attachment.SwapCustomData(customData); + } + revision = s.ColumnInt(6); return true; } @@ -1827,18 +1848,25 @@ static_cast<CompressionType>(s.ColumnInt(2)), s.ColumnInt64(3), s.ColumnString(5)); - attachment.SetCustomData(s.ColumnString(7)); // TODO_ATTACH_CUSTOM_DATA TODO TODO + + std::string customData; + if (s.ColumnBlobAsString(7, &customData)) + { + attachment.SwapCustomData(customData); + } + revision = s.ColumnInt(6); return true; } } virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) ORTHANC_OVERRIDE + const void* customData, + size_t customDataSize) ORTHANC_OVERRIDE { SQLite::Statement s(db_, SQLITE_FROM_HERE, "UPDATE AttachedFiles SET customData=? WHERE uuid=?"); - s.BindString(0, customData); + s.BindBlob(0, customData, customDataSize); s.BindString(1, attachmentUuid); s.Run(); } @@ -2376,7 +2404,7 @@ static_cast<CompressionType>(context.GetIntValue(3)), static_cast<uint64_t>(context.GetInt64Value(4)), compressedMD5); - info.SetCustomData(customData); + info.SwapCustomData(customData); sqlite_.activeTransaction_->GetListener().SignalAttachmentDeleted(info); sqlite_.activeTransaction_->DeleteDeletedFile(id);
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -3590,29 +3590,33 @@ } void StatelessDatabaseOperations::UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) + const void* customData, + size_t customDataSize) { class Operations : public IReadWriteOperations { private: const std::string& attachmentUuid_; - const std::string& customData_; + const void* customData_; + size_t customDataSize_; public: Operations(const std::string& attachmentUuid, - const std::string& customData) : + const void* customData, + size_t customDataSize) : attachmentUuid_(attachmentUuid), - customData_(customData) + customData_(customData), + customDataSize_(customDataSize) { } virtual void Apply(ReadWriteTransaction& transaction) ORTHANC_OVERRIDE { - transaction.UpdateAttachmentCustomData(attachmentUuid_, customData_); + transaction.UpdateAttachmentCustomData(attachmentUuid_, customData_, customDataSize_); } }; - Operations operations(attachmentUuid, customData); + Operations operations(attachmentUuid, customData, customDataSize); Apply(operations); }
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Sat Jun 07 18:50:42 2025 +0200 @@ -487,9 +487,10 @@ } void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData) + const void* customData, + size_t customDataSize) { - return transaction_.UpdateAttachmentCustomData(attachmentUuid, customData); + return transaction_.UpdateAttachmentCustomData(attachmentUuid, customData, customDataSize); } }; @@ -592,7 +593,8 @@ const std::string& attachmentUuid); void UpdateAttachmentCustomData(const std::string& attachmentUuid, - const std::string& customData); + const void* customData, + size_t customDataSize); bool LookupAttachment(FileInfo& attachment, int64_t& revision,
--- a/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Sat Jun 07 17:40:48 2025 +0200 +++ b/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Sat Jun 07 18:50:42 2025 +0200 @@ -1318,3 +1318,42 @@ db.Close(); } + + +TEST_F(DatabaseWrapperTest, BinaryCustomData) +{ + int64_t patient = transaction_->CreateResource("Patient", ResourceType_Patient); + + { + FileInfo info("hello", FileContentType_Dicom, 10, "md5"); + + { + std::string blob; + blob.push_back(0); + blob.push_back(1); + blob.push_back(0); + blob.push_back(2); + info.SetCustomData(blob); + } + + transaction_->AddAttachment(patient, info, 43); + } + + { + FileInfo info; + int64_t revision; + ASSERT_TRUE(transaction_->LookupAttachment(info, revision, patient, FileContentType_Dicom)); + ASSERT_EQ(43u, revision); + ASSERT_EQ("hello", info.GetUuid()); + ASSERT_EQ(CompressionType_None, info.GetCompressionType()); + ASSERT_EQ(10u, info.GetCompressedSize()); + ASSERT_EQ("md5", info.GetCompressedMD5()); + ASSERT_EQ(4u, info.GetCustomData().size()); + ASSERT_EQ(0, static_cast<uint8_t>(info.GetCustomData()[0])); + ASSERT_EQ(1, static_cast<uint8_t>(info.GetCustomData()[1])); + ASSERT_EQ(0, static_cast<uint8_t>(info.GetCustomData()[2])); + ASSERT_EQ(2, static_cast<uint8_t>(info.GetCustomData()[3])); + } + + transaction_->DeleteResource(patient); +} \ No newline at end of file