changeset 682:017d72dd27fa attach-custom-data

field "customData" is BYTEA
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Jun 2025 21:35:17 +0200
parents c652b6bf413e
children 4d46dc4fcc63
files Framework/Common/BinaryStringValue.cpp Framework/Common/BinaryStringValue.h Framework/Common/Dictionary.cpp Framework/Common/Dictionary.h Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexUnitTests.h PostgreSQL/Plugins/SQL/PrepareIndex.sql PostgreSQL/Plugins/SQL/Upgrades/Rev4ToRev5.sql
diffstat 8 files changed, 73 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Common/BinaryStringValue.cpp	Sat May 31 09:31:55 2025 +0200
+++ b/Framework/Common/BinaryStringValue.cpp	Mon Jun 09 21:35:17 2025 +0200
@@ -31,6 +31,20 @@
 
 namespace OrthancDatabases
 {
+  BinaryStringValue::BinaryStringValue(const void* data,
+                                       size_t size)
+  {
+    if (data == NULL && size > 0)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+    }
+    else
+    {
+      content_.assign(reinterpret_cast<const char*>(data), size);
+    }
+  }
+
+
   IValue* BinaryStringValue::Convert(ValueType target) const
   {
     switch (target)
--- a/Framework/Common/BinaryStringValue.h	Sat May 31 09:31:55 2025 +0200
+++ b/Framework/Common/BinaryStringValue.h	Mon Jun 09 21:35:17 2025 +0200
@@ -44,6 +44,9 @@
     {
     }
 
+    BinaryStringValue(const void* data,
+                      size_t size);
+
     const std::string& GetContent() const
     {
       return content_;
--- a/Framework/Common/Dictionary.cpp	Sat May 31 09:31:55 2025 +0200
+++ b/Framework/Common/Dictionary.cpp	Mon Jun 09 21:35:17 2025 +0200
@@ -106,6 +106,14 @@
   }
 
   
+  void Dictionary::SetBinaryValue(const std::string& key,
+                                  const void* data,
+                                  size_t size)
+  {
+    SetValue(key, new BinaryStringValue(data, size));
+  }
+
+
   void Dictionary::SetFileValue(const std::string& key,
                                 const std::string& file)
   {
--- a/Framework/Common/Dictionary.h	Sat May 31 09:31:55 2025 +0200
+++ b/Framework/Common/Dictionary.h	Mon Jun 09 21:35:17 2025 +0200
@@ -63,6 +63,10 @@
     void SetBinaryValue(const std::string& key,
                         const std::string& binary);
 
+    void SetBinaryValue(const std::string& key,
+                        const void* data,
+                        size_t size);
+
     void SetFileValue(const std::string& key,
                       const std::string& file);
 
--- a/Framework/Plugins/IndexBackend.cpp	Sat May 31 09:31:55 2025 +0200
+++ b/Framework/Plugins/IndexBackend.cpp	Mon Jun 09 21:35:17 2025 +0200
@@ -273,6 +273,8 @@
     statement.SetReadOnly(true);
     statement.Execute();
 
+    statement.SetResultFieldType(8, ValueType_BinaryString);
+
     while (!statement.IsDone())
     {
       output.SignalDeletedAttachment(statement.ReadString(0),
@@ -362,7 +364,8 @@
                                    int32_t     compressionType,
                                    uint64_t    compressedSize,
                                    const char* compressedHash,
-                                   const char* customData,
+                                   const void* customData,
+                                   size_t      customDataSize,
                                    int64_t     revision)
   {
     DatabaseManager::CachedStatement statement(
@@ -392,14 +395,7 @@
     args.SetUtf8Value("hash", uncompressedHash);
     args.SetUtf8Value("hash-compressed", compressedHash);
     args.SetIntegerValue("revision", revision);
-    if (customData != NULL && strlen(customData) > 0)
-    {
-      args.SetUtf8Value("custom-data", customData);
-    }
-    else
-    {
-      args.SetUtf8NullValue("custom-data");
-    }
+    args.SetBinaryValue("custom-data", customData, customDataSize);
 
     statement.Execute(args);
   }
@@ -412,7 +408,7 @@
   {
     assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // all plugins support these features now
     ExecuteAddAttachment(manager, id, attachment.uuid, attachment.contentType, attachment.uncompressedSize, attachment.uncompressedHash,
-                         attachment.compressionType, attachment.compressedSize, attachment.compressedHash, "", revision);
+                         attachment.compressionType, attachment.compressedSize, attachment.compressedHash, NULL, 0, revision);
   }
 
 #if ORTHANC_PLUGINS_HAS_ATTACHMENTS_CUSTOM_DATA
@@ -430,7 +426,8 @@
                          request.attachment().compression_type(),
                          request.attachment().compressed_size(),
                          request.attachment().compressed_hash().c_str(),
-                         request.attachment().custom_data().c_str(),
+                         request.attachment().custom_data().empty() ? NULL : request.attachment().custom_data().c_str(),
+                         request.attachment().custom_data().size(),
                          request.revision());
   }
 #endif
@@ -1223,6 +1220,7 @@
     args.SetIntegerValue("type", static_cast<int>(contentType));
 
     statement.Execute(args);
+    statement.SetResultFieldType(7, ValueType_BinaryString);
 
     if (statement.IsDone())
     {
@@ -1242,10 +1240,7 @@
       }
 
       std::string customData;
-      if (statement.GetResultField(7).GetType() == ValueType_Utf8String) // column has been added in 1.12.0
-      {
-        customData = statement.ReadString(7);
-      }
+      customData = statement.ReadStringOrNull(7);
 
       output.AnswerAttachment(statement.ReadString(0),
                               contentType,
@@ -3447,7 +3442,7 @@
           "  Lookup.publicId AS c3_string1, "
           "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
           "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-          "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+          "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
           "  " + formatter.FormatNull("INT") + " AS c7_int1, "
           "  " + formatter.FormatNull("INT") + " AS c8_int2, "
           "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3465,7 +3460,7 @@
              "  value AS c3_string1, "
              "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
              "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-             "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+             "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
              "  tagGroup AS c7_int1, "
              "  tagElement AS c8_int2, "
              "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3485,7 +3480,7 @@
              "  value AS c3_string1, "
              "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
              "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-             "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+             "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
              "  type AS c7_int1, "
              + revisionInC7 +
              "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3525,7 +3520,7 @@
              "  label AS c3_string1, "
              "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
              "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-             "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+             "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
              "  " + formatter.FormatNull("INT") + " AS c7_int1, "
              "  " + formatter.FormatNull("INT") + " AS c8_int2, "
              "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3564,7 +3559,7 @@
                "  value AS c3_string1, "
                "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-               "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+               "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                "  tagGroup AS c7_int1, "
                "  tagElement AS c8_int2, "
                "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3584,7 +3579,7 @@
                "  value AS c3_string1, "
                "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-               "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+               "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                "  type AS c7_int1, "
                + revisionInC7 +
                "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3621,7 +3616,7 @@
                "  value AS c3_string1, "
                "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-               "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+               "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                "  tagGroup AS c7_int1, "
                "  tagElement AS c8_int2, "
                "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3642,7 +3637,7 @@
                 "  value AS c3_string1, "
                 "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                 "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                 "  type AS c7_int1, "
                 + revisionInC7 +
                 "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3670,7 +3665,7 @@
                "  value AS c3_string1, "
                "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-               "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+               "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                "  tagGroup AS c7_int1, "
                "  tagElement AS c8_int2, "
                "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3691,7 +3686,7 @@
                "  childLevel.publicId AS c3_string1, "
                "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-               "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+               "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3727,7 +3722,7 @@
                 "  " + formatter.FormatNull("TEXT") + " AS c3_string1, "
                 "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                 "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                 "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                 "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                 "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3750,7 +3745,7 @@
                 "  " + formatter.FormatNull("TEXT") + " AS c3_string1, "
                 "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                 "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                 "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                 "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                 "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3770,7 +3765,7 @@
                 "  value AS c3_string1, "
                 "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                 "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                 "  type AS c7_int1, "
                 + revisionInC7 +
                 "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3795,7 +3790,7 @@
                 "  grandChildLevel.publicId AS c3_string1, "
                 "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                 "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                 "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                 "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                 "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3839,7 +3834,7 @@
                     "  " + formatter.FormatNull("TEXT") + " AS c3_string1, "
                     "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                     "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                    "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                    "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                     "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                     "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                     "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3862,7 +3857,7 @@
                   "  " + formatter.FormatNull("TEXT") + " AS c3_string1, "
                   "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                   "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                  "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                  "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                   "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                   "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                   "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3883,7 +3878,7 @@
                  "  value AS c3_string1, "
                  "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                  "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                 "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                 "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                  "  tagGroup AS c7_int1, "
                  "  tagElement AS c8_int2, "
                  "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3904,7 +3899,7 @@
                  "  value AS c3_string1, "
                  "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                  "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                 "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                 "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                  "  type AS c7_int1, "
                  + revisionInC7 +
                  "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3930,7 +3925,7 @@
                   "  grandGrandChildLevel.publicId AS c3_string1, "
                   "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                   "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                  "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                  "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                   "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                   "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                   "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3975,7 +3970,7 @@
                     "  " + formatter.FormatNull("TEXT") + " AS c3_string1, "
                     "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                     "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                    "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                    "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                     "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                     "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                     "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -3999,7 +3994,7 @@
                     "  " + formatter.FormatNull("TEXT") + " AS c3_string1, "
                     "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
                     "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-                    "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+                    "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
                     "  " + formatter.FormatNull("INT") + " AS c7_int1, "
                     "  " + formatter.FormatNull("INT") + " AS c8_int2, "
                     "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -4025,7 +4020,7 @@
              "  parentLevel.publicId AS c3_string1, "
              "  " + formatter.FormatNull("TEXT") + " AS c4_string2, "
              "  " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-             "  " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+             "  " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
              "  " + formatter.FormatNull("INT") + " AS c7_int1, "
              "  " + formatter.FormatNull("INT") + " AS c8_int2, "
              "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -4047,7 +4042,7 @@
              "    instancePublicId AS c3_string1, "
              "    " + formatter.FormatNull("TEXT") + " AS c4_string2, "
              "    " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-             "    " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+             "    " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
              "    " + formatter.FormatNull("INT") + " AS c7_int1, "
              "    " + formatter.FormatNull("INT") + " AS c8_int2, "
              "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -4062,7 +4057,7 @@
              "    Metadata.value AS c3_string1, "
              "    " + formatter.FormatNull("TEXT") + " AS c4_string2, "
              "    " + formatter.FormatNull("TEXT") + " AS c5_string3, "
-             "    " + formatter.FormatNull("TEXT") + " AS c6_string4, "
+             "    " + formatter.FormatNull("BYTEA") + " AS c6_string4, "
              "    Metadata.type AS c7_int1, "
              + revisionInC7 +
              "  " + formatter.FormatNull("INT") + " AS c9_int3, "
@@ -4107,7 +4102,9 @@
     }
     
     statement->Execute(formatter.GetDictionary());
-    
+
+    statement->SetResultFieldType(C6_STRING_4, ValueType_BinaryString);
+
     // LOG(INFO) << sql;
 
     std::map<int64_t, Orthanc::DatabasePluginMessages::Find_Response*> responses;
@@ -4614,6 +4611,7 @@
       args.SetUtf8Value("uuid", request.uuid());
 
       statement.Execute(args);
+      statement.SetResultFieldType(8, ValueType_BinaryString);
 
       if (statement.IsDone())
       {
@@ -4649,16 +4647,8 @@
 
       Dictionary args;
       args.SetUtf8Value("uuid", attachmentUuid);
-
-      if (customData.empty())
-      {
-        args.SetUtf8NullValue("customData");
-      }
-      else
-      {
-        args.SetUtf8Value("customData", customData);
-      }
-      
+      args.SetBinaryValue("customData", customData);
+
       statement.Execute(args);
     }
 #endif
--- a/Framework/Plugins/IndexUnitTests.h	Sat May 31 09:31:55 2025 +0200
+++ b/Framework/Plugins/IndexUnitTests.h	Mon Jun 09 21:35:17 2025 +0200
@@ -314,7 +314,7 @@
 #elif ORTHANC_ENABLE_ODBC == 1
   OdbcIndex db(&context, connectionString_, false);
 #elif ORTHANC_ENABLE_SQLITE == 1  // Must be the last one
-  SQLiteIndex db(&context, "tutu.db");  // Open in memory
+  SQLiteIndex db(&context);  // Open in memory
 #else
 #  error Unsupported database backend
 #endif
--- a/PostgreSQL/Plugins/SQL/PrepareIndex.sql	Sat May 31 09:31:55 2025 +0200
+++ b/PostgreSQL/Plugins/SQL/PrepareIndex.sql	Mon Jun 09 21:35:17 2025 +0200
@@ -53,7 +53,7 @@
        uncompressedHash VARCHAR(40),
        compressedHash VARCHAR(40),
        revision INTEGER,
-       customData TEXT,              -- new in schema rev 5
+       customData BYTEA,           -- new in schema rev 5
        PRIMARY KEY(id, fileType)
        );              
 
@@ -733,7 +733,7 @@
 CREATE TABLE Queues (
        id BIGSERIAL NOT NULL PRIMARY KEY,
        queueId TEXT NOT NULL,
-       value BYTEA
+       value BYTEA NOT NULL
 );
 
 CREATE INDEX QueuesIndex ON Queues (queueId, id);
--- a/PostgreSQL/Plugins/SQL/Upgrades/Rev4ToRev5.sql	Sat May 31 09:31:55 2025 +0200
+++ b/PostgreSQL/Plugins/SQL/Upgrades/Rev4ToRev5.sql	Mon Jun 09 21:35:17 2025 +0200
@@ -11,7 +11,7 @@
 BEGIN
 
     BEGIN
-        ALTER TABLE AttachedFiles ADD COLUMN customData TEXT;
+        ALTER TABLE AttachedFiles ADD COLUMN customData BYTEA;
     EXCEPTION
         WHEN duplicate_column THEN RAISE NOTICE 'column customData already exists in AttachedFiles.';
     END;