changeset 638:354d4c617387 attach-custom-data

cleanup + improved handling of null values
author Alain Mazy <am@orthanc.team>
date Tue, 04 Feb 2025 17:12:58 +0100 (4 months ago)
parents c97f7b180293
children e5051580aeac
files Framework/MySQL/MySQLStatement.cpp Framework/Plugins/DatabaseBackendAdapterV4.cpp Framework/Plugins/IDatabaseBackend.h Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexBackend.h Framework/PostgreSQL/PostgreSQLStatement.cpp
diffstat 6 files changed, 99 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/MySQL/MySQLStatement.cpp	Fri Jan 31 11:08:37 2025 +0100
+++ b/Framework/MySQL/MySQLStatement.cpp	Tue Feb 04 17:12:58 2025 +0100
@@ -468,62 +468,64 @@
         throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem);
       }
 
-      ValueType type = formatter_.GetParameterType(i);
-
       const IValue& value = parameters.GetValue(name);
-      if (value.GetType() != type)
-      {
-        LOG(ERROR) << "Bad type of argument provided to a SQL query: " << name;
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType);
-      }
 
-      // https://dev.mysql.com/doc/refman/8.0/en/c-api-prepared-statement-type-codes.html
-      switch (type)
+      if (value.GetType() == ValueType_Null)
       {
-        case ValueType_Integer64:
+        inputs[i].buffer = NULL;
+        inputs[i].buffer_type = MYSQL_TYPE_NULL;
+      }
+      else
+      {
+        ValueType type = formatter_.GetParameterType(i);
+  
+        if (value.GetType() != type)
         {
-          int64Parameters.push_back(dynamic_cast<const Integer64Value&>(value).GetValue());
-          inputs[i].buffer = &int64Parameters.back();
-          inputs[i].buffer_type = MYSQL_TYPE_LONGLONG;
-          break;
+          LOG(ERROR) << "Bad type of argument provided to a SQL query: " << name;
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType);
         }
 
-        case ValueType_Utf8String:
+        // https://dev.mysql.com/doc/refman/8.0/en/c-api-prepared-statement-type-codes.html
+        switch (type)
         {
-          const std::string& utf8 = dynamic_cast<const Utf8StringValue&>(value).GetContent();
-          inputs[i].buffer = const_cast<char*>(utf8.c_str());
-          inputs[i].buffer_length = utf8.size();
-          inputs[i].buffer_type = MYSQL_TYPE_STRING;
-          break;
-        }
+          case ValueType_Integer64:
+          {
+            int64Parameters.push_back(dynamic_cast<const Integer64Value&>(value).GetValue());
+            inputs[i].buffer = &int64Parameters.back();
+            inputs[i].buffer_type = MYSQL_TYPE_LONGLONG;
+            break;
+          }
 
-        case ValueType_BinaryString:
-        {
-          const std::string& content = dynamic_cast<const BinaryStringValue&>(value).GetContent();
-          inputs[i].buffer = const_cast<char*>(content.c_str());
-          inputs[i].buffer_length = content.size();
-          inputs[i].buffer_type = MYSQL_TYPE_BLOB;
-          break;
-        }
+          case ValueType_Utf8String:
+          {
+            const std::string& utf8 = dynamic_cast<const Utf8StringValue&>(value).GetContent();
+            inputs[i].buffer = const_cast<char*>(utf8.c_str());
+            inputs[i].buffer_length = utf8.size();
+            inputs[i].buffer_type = MYSQL_TYPE_STRING;
+            break;
+          }
 
-        case ValueType_InputFile:
-        {
-          const std::string& content = dynamic_cast<const InputFileValue&>(value).GetContent();
-          inputs[i].buffer = const_cast<char*>(content.c_str());
-          inputs[i].buffer_length = content.size();
-          inputs[i].buffer_type = MYSQL_TYPE_BLOB;
-          break;
-        }
+          case ValueType_BinaryString:
+          {
+            const std::string& content = dynamic_cast<const BinaryStringValue&>(value).GetContent();
+            inputs[i].buffer = const_cast<char*>(content.c_str());
+            inputs[i].buffer_length = content.size();
+            inputs[i].buffer_type = MYSQL_TYPE_BLOB;
+            break;
+          }
 
-        case ValueType_Null:
-        {
-          inputs[i].buffer = NULL;
-          inputs[i].buffer_type = MYSQL_TYPE_NULL;
-          break;
+          case ValueType_InputFile:
+          {
+            const std::string& content = dynamic_cast<const InputFileValue&>(value).GetContent();
+            inputs[i].buffer = const_cast<char*>(content.c_str());
+            inputs[i].buffer_length = content.size();
+            inputs[i].buffer_type = MYSQL_TYPE_BLOB;
+            break;
+          }
+
+          default:
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
         }
-
-        default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
       }
     }
 
--- a/Framework/Plugins/DatabaseBackendAdapterV4.cpp	Fri Jan 31 11:08:37 2025 +0100
+++ b/Framework/Plugins/DatabaseBackendAdapterV4.cpp	Tue Feb 04 17:12:58 2025 +0100
@@ -690,7 +690,7 @@
       
       case Orthanc::DatabasePluginMessages::OPERATION_ADD_ATTACHMENT:
       {
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 7)
+#if ORTHANC_PLUGINS_HAS_ATTACHMENTS_CUSTOM_DATA
         backend.AddAttachment(response, manager, request.add_attachment());
 #else
         OrthancPluginAttachment attachment;
--- a/Framework/Plugins/IDatabaseBackend.h	Fri Jan 31 11:08:37 2025 +0100
+++ b/Framework/Plugins/IDatabaseBackend.h	Tue Feb 04 17:12:58 2025 +0100
@@ -66,21 +66,13 @@
                                const OrthancPluginAttachment& attachment,
                                int64_t revision) = 0;
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 6)
-    // New in Orthanc 1.12.6
+#if ORTHANC_PLUGINS_HAS_ATTACHMENTS_CUSTOM_DATA
+    // New in Orthanc 1.12.7
     virtual void AddAttachment(Orthanc::DatabasePluginMessages::TransactionResponse& response,
                                DatabaseManager& manager,
                                const Orthanc::DatabasePluginMessages::AddAttachment_Request& request) = 0;
 #endif
 
-// #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 6)
-
-//     virtual void AddAttachment2(DatabaseManager& manager,
-//                                int64_t id,
-//                                const OrthancPluginAttachment2& attachment,
-//                                int64_t revision) = 0;
-// #endif
-
     virtual void AttachChild(DatabaseManager& manager,
                              int64_t parent,
                              int64_t child) = 0;
--- a/Framework/Plugins/IndexBackend.cpp	Fri Jan 31 11:08:37 2025 +0100
+++ b/Framework/Plugins/IndexBackend.cpp	Tue Feb 04 17:12:58 2025 +0100
@@ -392,7 +392,14 @@
     args.SetUtf8Value("hash", uncompressedHash);
     args.SetUtf8Value("hash-compressed", compressedHash);
     args.SetIntegerValue("revision", revision);
-    args.SetUtf8Value("custom-data", customData);
+    if (customData != NULL && strlen(customData) > 0)
+    {
+      args.SetUtf8Value("custom-data", customData);
+    }
+    else
+    {
+      args.SetNullValue("custom-data");
+    }
 
     statement.Execute(args);
   }
@@ -403,17 +410,17 @@
                                    const OrthancPluginAttachment& attachment,
                                    int64_t revision)
   {
-    assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // all plugins supports these features now
+    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);
   }
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 7)
+#if ORTHANC_PLUGINS_HAS_ATTACHMENTS_CUSTOM_DATA
   void IndexBackend::AddAttachment(Orthanc::DatabasePluginMessages::TransactionResponse& response,
                                    DatabaseManager& manager,
                                    const Orthanc::DatabasePluginMessages::AddAttachment_Request& request)
   {
-    assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // all plugins supports these features now
+    assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // all plugins support these features now
     ExecuteAddAttachment(manager, 
                          request.id(), 
                          request.attachment().uuid().c_str(),
@@ -1194,14 +1201,13 @@
   }
 
     
-  /* Use GetOutput().AnswerAttachment() */
   bool IndexBackend::LookupAttachment(IDatabaseBackendOutput& output,
                                       int64_t& revision /*out*/,
                                       DatabaseManager& manager,
                                       int64_t id,
                                       int32_t contentType)
   {
-    assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // we force v4 plugins to support both ! 
+    assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // we have forced all v4 plugins to support both ! 
     DatabaseManager::CachedStatement statement(
       STATEMENT_FROM_HERE, manager,
       "SELECT uuid, uncompressedSize, compressionType, compressedSize, uncompressedHash, "
@@ -1241,7 +1247,6 @@
         customData = statement.ReadString(7);
       }
 
-
       output.AnswerAttachment(statement.ReadString(0),
                               contentType,
                               statement.ReadInteger64(1),
@@ -4210,7 +4215,7 @@
           attachment->set_uuid(statement->ReadString(C3_STRING_1));
           attachment->set_uncompressed_hash(statement->ReadString(C4_STRING_2));
           attachment->set_compressed_hash(statement->ReadString(C5_STRING_3));
-          attachment->set_custom_data(statement->ReadString(C6_STRING_4));
+          attachment->set_custom_data(statement->ReadStringOrNull(C6_STRING_4));
           attachment->set_content_type(statement->ReadInteger32(C7_INT_1));
           attachment->set_compression_type(statement->ReadInteger32(C9_INT_3));
           attachment->set_compressed_size(statement->ReadInteger64(C10_BIG_INT_1));
@@ -4312,7 +4317,7 @@
           attachment->set_uuid(statement->ReadString(C3_STRING_1));
           attachment->set_uncompressed_hash(statement->ReadString(C4_STRING_2));
           attachment->set_compressed_hash(statement->ReadString(C5_STRING_3));
-          attachment->set_custom_data(statement->ReadString(C6_STRING_4));
+          attachment->set_custom_data(statement->ReadStringOrNull(C6_STRING_4));
           attachment->set_content_type(statement->ReadInteger32(C7_INT_1));
           attachment->set_compression_type(statement->ReadInteger32(C9_INT_3));
           attachment->set_compressed_size(statement->ReadInteger64(C10_BIG_INT_1));
--- a/Framework/Plugins/IndexBackend.h	Fri Jan 31 11:08:37 2025 +0100
+++ b/Framework/Plugins/IndexBackend.h	Tue Feb 04 17:12:58 2025 +0100
@@ -100,7 +100,7 @@
                                const OrthancPluginAttachment& attachment,
                                int64_t revision) ORTHANC_OVERRIDE;
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 7)
+#if ORTHANC_PLUGINS_HAS_ATTACHMENTS_CUSTOM_DATA
     // New in Orthanc 1.12.7
     virtual void AddAttachment(Orthanc::DatabasePluginMessages::TransactionResponse& response,
                                DatabaseManager& manager,
--- a/Framework/PostgreSQL/PostgreSQLStatement.cpp	Fri Jan 31 11:08:37 2025 +0100
+++ b/Framework/PostgreSQL/PostgreSQLStatement.cpp	Tue Feb 04 17:12:58 2025 +0100
@@ -528,42 +528,47 @@
     {
       const std::string& name = formatter_.GetParameterName(i);
       
-      switch (formatter_.GetParameterType(i))
-      {
-        case ValueType_Integer64:
-          BindInteger64(i, dynamic_cast<const Integer64Value&>(parameters.GetValue(name)).GetValue());
-          break;
+      const IValue& value = parameters.GetValue(name);
 
-        case ValueType_Integer32:
-          BindInteger(i, dynamic_cast<const Integer32Value&>(parameters.GetValue(name)).GetValue());
-          break;
+      if (value.GetType() == ValueType_Null)
+      {
+        BindNull(i);
+      }
+      else
+      {
+        switch (formatter_.GetParameterType(i))
+        {
+          case ValueType_Integer64:
+            BindInteger64(i, dynamic_cast<const Integer64Value&>(parameters.GetValue(name)).GetValue());
+            break;
 
-        case ValueType_Null:
-          BindNull(i);
-          break;
+          case ValueType_Integer32:
+            BindInteger(i, dynamic_cast<const Integer32Value&>(parameters.GetValue(name)).GetValue());
+            break;
 
-        case ValueType_Utf8String:
-          BindString(i, dynamic_cast<const Utf8StringValue&>
-                     (parameters.GetValue(name)).GetContent());
-          break;
+          case ValueType_Utf8String:
+            BindString(i, dynamic_cast<const Utf8StringValue&>
+                      (parameters.GetValue(name)).GetContent());
+            break;
 
-        case ValueType_BinaryString:
-          BindString(i, dynamic_cast<const BinaryStringValue&>
-                     (parameters.GetValue(name)).GetContent());
-          break;
+          case ValueType_BinaryString:
+            BindString(i, dynamic_cast<const BinaryStringValue&>
+                      (parameters.GetValue(name)).GetContent());
+            break;
 
-        case ValueType_InputFile:
-        {
-          const InputFileValue& blob =
-            dynamic_cast<const InputFileValue&>(parameters.GetValue(name));
+          case ValueType_InputFile:
+          {
+            const InputFileValue& blob =
+              dynamic_cast<const InputFileValue&>(parameters.GetValue(name));
 
-          PostgreSQLLargeObject largeObject(database_, blob.GetContent());
-          BindLargeObject(i, largeObject);
-          break;
+            PostgreSQLLargeObject largeObject(database_, blob.GetContent());
+            BindLargeObject(i, largeObject);
+            break;
+          }
+
+          default:
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
         }
-
-        default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
       }
     }