changeset 117:ca0ecd412988 OrthancMySQL-2.0

Implementation of new extensions: LookupResourceAndParent and GetAllMetadata
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 04 Feb 2019 16:03:17 +0100
parents 569e17419eae
children c9eb54785de6 260fc55f10cd
files Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexBackend.h Framework/Plugins/OrthancCppDatabasePlugin.h MySQL/NEWS PostgreSQL/NEWS
diffstat 5 files changed, 229 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Plugins/IndexBackend.cpp	Wed Jan 30 17:05:49 2019 +0100
+++ b/Framework/Plugins/IndexBackend.cpp	Mon Feb 04 16:03:17 2019 +0100
@@ -1739,9 +1739,9 @@
       args.SetUtf8Value(name, tags[i].value);
       
       std::string insert = ("(" + boost::lexical_cast<std::string>(tags[i].resource) + ", " +
-                           boost::lexical_cast<std::string>(tags[i].group) + ", " +
-                           boost::lexical_cast<std::string>(tags[i].element) + ", " +
-                           "${" + name + "})");
+                            boost::lexical_cast<std::string>(tags[i].group) + ", " +
+                            boost::lexical_cast<std::string>(tags[i].element) + ", " +
+                            "${" + name + "})");
 
       if (sql.empty())
       {
@@ -1787,7 +1787,7 @@
       
       std::string insert = ("(" + boost::lexical_cast<std::string>(metadata[i].resource) + ", " +
                             boost::lexical_cast<std::string>(metadata[i].metadata) + ", " +
-                           "${" + name + "})");
+                            "${" + name + "})");
 
       std::string remove = ("(id=" + boost::lexical_cast<std::string>(metadata[i].resource) +
                             " AND type=" + boost::lexical_cast<std::string>(metadata[i].metadata)
@@ -1951,4 +1951,108 @@
       statement.Execute(args);
     }
   }
+
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+  // New primitive since Orthanc 1.5.4
+  bool IndexBackend::LookupResourceAndParent(int64_t& id,
+                                             OrthancPluginResourceType& type,
+                                             std::string& parentPublicId,
+                                             const char* publicId)
+  {
+    DatabaseManager::CachedStatement statement(
+      STATEMENT_FROM_HERE, manager_,
+      "SELECT resource.internalId, resource.resourceType, parent.publicId "
+      "FROM Resources AS resource LEFT JOIN Resources parent ON parent.internalId=resource.parentId "
+      "WHERE resource.publicId=${id}");
+
+    statement.SetParameterType("id", ValueType_Utf8String);
+        
+    Dictionary args;
+    args.SetUtf8Value("id", publicId);
+
+    statement.Execute(args);
+
+    if (statement.IsDone())
+    {
+      return false;
+    }
+    else
+    {
+      if (statement.GetResultFieldsCount() != 3)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+
+      statement.SetResultFieldType(0, ValueType_Integer64);
+      statement.SetResultFieldType(1, ValueType_Integer64);      
+      statement.SetResultFieldType(2, ValueType_Utf8String);
+
+      id = ReadInteger64(statement, 0);
+      type = static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 1));
+
+      const IValue& value = statement.GetResultField(2);
+      
+      switch (value.GetType())
+      {
+        case ValueType_Null:
+          parentPublicId.clear();
+          break;
+
+        case ValueType_Utf8String:
+          parentPublicId = dynamic_cast<const Utf8StringValue&>(value).GetContent();
+          break;
+
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+      
+      assert((statement.Next(), statement.IsDone()));
+      return true;
+    }
+  }
+#  endif
+#endif
+  
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+  // New primitive since Orthanc 1.5.4
+  void IndexBackend::GetAllMetadata(std::map<int32_t, std::string>& result,
+                                    int64_t id)
+  {
+    DatabaseManager::CachedStatement statement(
+      STATEMENT_FROM_HERE, manager_,
+      "SELECT type, value FROM Metadata WHERE id=${id}");
+      
+    statement.SetReadOnly(true);
+    statement.SetParameterType("id", ValueType_Integer64);
+
+    Dictionary args;
+    args.SetIntegerValue("id", id);
+
+    statement.Execute(args);
+      
+    result.clear();
+
+    if (!statement.IsDone())
+    {
+      if (statement.GetResultFieldsCount() != 2)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+      
+      statement.SetResultFieldType(0, ValueType_Integer64);
+      statement.SetResultFieldType(1, ValueType_Utf8String);
+
+      while (!statement.IsDone())
+      {
+        result[ReadInteger32(statement, 0)] = ReadString(statement, 1);
+        statement.Next();
+      }
+    }
+  }
+#  endif
+#endif
 }
--- a/Framework/Plugins/IndexBackend.h	Wed Jan 30 17:05:49 2019 +0100
+++ b/Framework/Plugins/IndexBackend.h	Mon Feb 04 16:03:17 2019 +0100
@@ -283,5 +283,23 @@
                                      int32_t metadata);
 
     virtual void TagMostRecentPatient(int64_t patient);
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+    // New primitive since Orthanc 1.5.4
+    virtual bool LookupResourceAndParent(int64_t& id,
+                                         OrthancPluginResourceType& type,
+                                         std::string& parentPublicId,
+                                         const char* publicId);
+#  endif
+#endif
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+    // New primitive since Orthanc 1.5.4
+    virtual void GetAllMetadata(std::map<int32_t, std::string>& result,
+                                int64_t id);
+#  endif
+#endif
   };
 }
--- a/Framework/Plugins/OrthancCppDatabasePlugin.h	Wed Jan 30 17:05:49 2019 +0100
+++ b/Framework/Plugins/OrthancCppDatabasePlugin.h	Mon Feb 04 16:03:17 2019 +0100
@@ -82,7 +82,8 @@
       AllowedAnswers_DicomTag,
       AllowedAnswers_ExportedResource,
       AllowedAnswers_MatchingResource,
-      AllowedAnswers_String
+      AllowedAnswers_String,
+      AllowedAnswers_Metadata
     };
 
     OrthancPluginContext*         context_;
@@ -534,6 +535,23 @@
     virtual int64_t GetLastChangeIndex() = 0;
 
     virtual void TagMostRecentPatient(int64_t patientId) = 0;
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+    // NB: "parentPublicId" must be cleared if the resource has no parent
+    virtual bool LookupResourceAndParent(int64_t& id,
+      OrthancPluginResourceType& type,
+      std::string& parentPublicId,
+      const char* publicId) = 0;
+#  endif
+#endif
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+  virtual void GetAllMetadata(std::map<int32_t, std::string>& result,
+                              int64_t id) = 0;
+#  endif
+#endif
   };
 
 
@@ -1650,6 +1668,77 @@
     }
    
 
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+    // New primitive since Orthanc 1.5.4
+    static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseContext* context,
+                                                 void* payload,
+                                                 int64_t resourceId)
+    {
+      IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
+      backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Metadata);
+
+      try
+      {
+        std::map<int32_t, std::string> result;
+        backend->GetAllMetadata(result, resourceId);
+
+        for (std::map<int32_t, std::string>::const_iterator
+               it = result.begin(); it != result.end(); ++it)
+        {
+          OrthancPluginDatabaseAnswerMetadata(backend->GetOutput().context_,
+                                            backend->GetOutput().database_,
+                                            resourceId, it->first, it->second.c_str());
+        }
+        
+        return OrthancPluginErrorCode_Success;
+      }
+      ORTHANC_PLUGINS_DATABASE_CATCH      
+    }
+#  endif
+#endif
+   
+
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+    // New primitive since Orthanc 1.5.4
+    static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseContext* context,
+                                                          uint8_t* isExisting,
+                                                          int64_t* id,
+                                                          OrthancPluginResourceType* type,
+                                                          void* payload,
+                                                          const char* publicId)
+    {
+      IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
+      backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_String);
+
+      try
+      {
+        std::string parent;
+        if (backend->LookupResourceAndParent(*id, *type, parent, publicId))
+        {
+          *isExisting = 1;
+
+          if (!parent.empty())
+          {
+            OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
+                                              backend->GetOutput().database_,
+                                              parent.c_str());
+          }
+        }
+        else
+        {
+          *isExisting = 0;
+        }
+        
+        return OrthancPluginErrorCode_Success;
+      }
+      ORTHANC_PLUGINS_DATABASE_CATCH      
+    }
+#  endif
+#endif
+   
+
   public:
     /**
      * Register a custom database back-end written in C++.
@@ -1741,11 +1830,18 @@
       {
         extensions.createInstance = CreateInstance;          // Fast creation of resources
       }
-      
-      performanceWarning = false;
 #endif      
 
-      if (performanceWarning)
+#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
+#  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
+      // Optimizations brought by Orthanc 1.5.4
+      extensions.lookupResourceAndParent = LookupResourceAndParent;
+      extensions.getAllMetadata = GetAllMetadata;
+      performanceWarning = false;
+#  endif
+#endif
+
+  if (performanceWarning)
       {
         char info[1024];
         sprintf(info, 
--- a/MySQL/NEWS	Wed Jan 30 17:05:49 2019 +0100
+++ b/MySQL/NEWS	Mon Feb 04 16:03:17 2019 +0100
@@ -1,6 +1,8 @@
 Pending changes in the mainline
 ===============================
 
+* Implementation of new extensions: LookupResourceAndParent and GetAllMetadata
+
 
 Release 2.0 (2019-01-23)
 ========================
--- a/PostgreSQL/NEWS	Wed Jan 30 17:05:49 2019 +0100
+++ b/PostgreSQL/NEWS	Mon Feb 04 16:03:17 2019 +0100
@@ -3,6 +3,7 @@
 
 * Fix build on Debian Buster
 * Remove "ASSERT" in SQL for compatibility with older releases of PostgreSQL
+* Implementation of new extensions: LookupResourceAndParent and GetAllMetadata
 
 
 Release 3.0 (2019-01-21)