changeset 401:a8774581adfc db-protobuf

replaced "WithLabels" and "WithoutLabels", by "Labels" and "LabelsConstraint"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 07 Apr 2023 22:32:15 +0200
parents 897253c21208
children 82921a29349a
files Framework/Plugins/DatabaseBackendAdapterV2.cpp Framework/Plugins/DatabaseBackendAdapterV3.cpp Framework/Plugins/DatabaseBackendAdapterV4.cpp Framework/Plugins/IDatabaseBackend.h Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexBackend.h Resources/Orthanc/Databases/ISqlLookupFormatter.cpp Resources/Orthanc/Databases/ISqlLookupFormatter.h
diffstat 8 files changed, 75 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Plugins/DatabaseBackendAdapterV2.cpp	Fri Apr 07 15:43:42 2023 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV2.cpp	Fri Apr 07 22:32:15 2023 +0200
@@ -1419,9 +1419,9 @@
         lookup.push_back(Orthanc::DatabaseConstraint(constraints[i]));
       }
         
-      std::set<std::string> noLabels;
-      adapter->GetBackend().LookupResources(*output, accessor.GetManager(), lookup, queryLevel,
-                                            noLabels, noLabels, limit, (requestSomeInstance != 0));
+      std::set<std::string> noLabel;
+      adapter->GetBackend().LookupResources(*output, accessor.GetManager(), lookup, queryLevel, noLabel,
+                                            Orthanc::LabelsConstraint_All, limit, (requestSomeInstance != 0));
       
       return OrthancPluginErrorCode_Success;
     }
--- a/Framework/Plugins/DatabaseBackendAdapterV3.cpp	Fri Apr 07 15:43:42 2023 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV3.cpp	Fri Apr 07 22:32:15 2023 +0200
@@ -1646,9 +1646,9 @@
         lookup.push_back(Orthanc::DatabaseConstraint(constraints[i]));
       }
         
-      std::set<std::string> noLabels;
-      t->GetBackend().LookupResources(t->GetOutput(), t->GetManager(), lookup, queryLevel,
-                                      noLabels, noLabels, limit, (requestSomeInstanceId != 0));
+      std::set<std::string> noLabel;
+      t->GetBackend().LookupResources(t->GetOutput(), t->GetManager(), lookup, queryLevel, noLabel,
+                                      Orthanc::LabelsConstraint_All, limit, (requestSomeInstanceId != 0));
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
--- a/Framework/Plugins/DatabaseBackendAdapterV4.cpp	Fri Apr 07 15:43:42 2023 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV4.cpp	Fri Apr 07 22:32:15 2023 +0200
@@ -568,21 +568,35 @@
 
     assert(values.size() == countValues);
 
-    std::set<std::string> withLabels, withoutLabels;
+    std::set<std::string> labels;
 
-    for (int i = 0; i < request.with_labels().size(); i++)
+    for (int i = 0; i < request.labels().size(); i++)
     {
-      withLabels.insert(request.with_labels(i));
+      labels.insert(request.labels(i));
     }
 
-    for (int i = 0; i < request.without_labels().size(); i++)
+    Orthanc::LabelsConstraint labelsConstraint;
+    switch (request.labels_constraint())
     {
-      withoutLabels.insert(request.without_labels(i));
+      case Orthanc::DatabasePluginMessages::LABELS_CONSTRAINT_ALL:
+        labelsConstraint = Orthanc::LabelsConstraint_All;
+        break;
+            
+      case Orthanc::DatabasePluginMessages::LABELS_CONSTRAINT_ANY:
+        labelsConstraint = Orthanc::LabelsConstraint_Any;
+        break;
+            
+      case Orthanc::DatabasePluginMessages::LABELS_CONSTRAINT_NONE:
+        labelsConstraint = Orthanc::LabelsConstraint_None;
+        break;
+            
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
-    
+
     Output output(response);
     backend.LookupResources(output, manager, lookup, Convert(request.query_level()),
-                            withLabels, withoutLabels, request.limit(), request.retrieve_instances_ids());
+                            labels, labelsConstraint, request.limit(), request.retrieve_instances_ids());
   }
 
   
--- a/Framework/Plugins/IDatabaseBackend.h	Fri Apr 07 15:43:42 2023 +0200
+++ b/Framework/Plugins/IDatabaseBackend.h	Fri Apr 07 22:32:15 2023 +0200
@@ -23,9 +23,10 @@
 
 #pragma once
 
-#include "IDatabaseBackendOutput.h"
+#include "../../Resources/Orthanc/Databases/ISqlLookupFormatter.h"
+#include "../Common/DatabaseManager.h"
 #include "../Common/DatabasesEnumerations.h"
-#include "../Common/DatabaseManager.h"
+#include "IDatabaseBackendOutput.h"
 
 #include <list>
 
@@ -271,8 +272,8 @@
                                  DatabaseManager& manager,
                                  const std::vector<Orthanc::DatabaseConstraint>& lookup,
                                  OrthancPluginResourceType queryLevel,
-                                 const std::set<std::string>& withLabels,     // New in Orthanc 1.12.0
-                                 const std::set<std::string>& withoutLabels,  // New in Orthanc 1.12.0
+                                 const std::set<std::string>& labels,         // New in Orthanc 1.12.0
+                                 Orthanc::LabelsConstraint labelsConstraint,  // New in Orthanc 1.12.0
                                  uint32_t limit,
                                  bool requestSomeInstance) = 0;
 #endif
--- a/Framework/Plugins/IndexBackend.cpp	Fri Apr 07 15:43:42 2023 +0200
+++ b/Framework/Plugins/IndexBackend.cpp	Fri Apr 07 22:32:15 2023 +0200
@@ -22,7 +22,6 @@
 
 #include "IndexBackend.h"
 
-#include "../../Resources/Orthanc/Databases/ISqlLookupFormatter.h"
 #include "../Common/BinaryStringValue.h"
 #include "../Common/Integer64Value.h"
 #include "../Common/Utf8StringValue.h"
@@ -2065,17 +2064,16 @@
                                      DatabaseManager& manager,
                                      const std::vector<Orthanc::DatabaseConstraint>& lookup,
                                      OrthancPluginResourceType queryLevel,
-                                     const std::set<std::string>& withLabels,
-                                     const std::set<std::string>& withoutLabels,
+                                     const std::set<std::string>& labels,
+                                     Orthanc::LabelsConstraint labelsConstraint,
                                      uint32_t limit,
                                      bool requestSomeInstance)
   {
     LookupFormatter formatter(manager.GetDialect());
 
     std::string sql;
-    Orthanc::ISqlLookupFormatter::Apply(
-      sql, formatter, lookup, Orthanc::Plugins::Convert(queryLevel),
-      withLabels, withoutLabels, limit);
+    Orthanc::ISqlLookupFormatter::Apply(sql, formatter, lookup, Orthanc::Plugins::Convert(queryLevel),
+                                        labels, labelsConstraint, limit);
 
     if (requestSomeInstance)
     {
--- a/Framework/Plugins/IndexBackend.h	Fri Apr 07 15:43:42 2023 +0200
+++ b/Framework/Plugins/IndexBackend.h	Fri Apr 07 22:32:15 2023 +0200
@@ -302,8 +302,8 @@
                                  DatabaseManager& manager,
                                  const std::vector<Orthanc::DatabaseConstraint>& lookup,
                                  OrthancPluginResourceType queryLevel,
-                                 const std::set<std::string>& withLabels,
-                                 const std::set<std::string>& withoutLabels,
+                                 const std::set<std::string>& labels,
+                                 Orthanc::LabelsConstraint labelsConstraint,
                                  uint32_t limit,
                                  bool requestSomeInstance) ORTHANC_OVERRIDE;
 #endif
--- a/Resources/Orthanc/Databases/ISqlLookupFormatter.cpp	Fri Apr 07 15:43:42 2023 +0200
+++ b/Resources/Orthanc/Databases/ISqlLookupFormatter.cpp	Fri Apr 07 22:32:15 2023 +0200
@@ -307,8 +307,8 @@
                                   ISqlLookupFormatter& formatter,
                                   const std::vector<DatabaseConstraint>& lookup,
                                   ResourceType queryLevel,
-                                  const std::set<std::string>& withLabels,
-                                  const std::set<std::string>& withoutLabels,
+                                  const std::set<std::string>& labels,
+                                  LabelsConstraint labelsConstraint,
                                   size_t limit)
   {
     assert(ResourceType_Patient < ResourceType_Study &&
@@ -384,20 +384,7 @@
 
     std::list<std::string> where;
 
-    if (!withLabels.empty())
-    {
-      std::list<std::string> labels;
-      for (std::set<std::string>::const_iterator it = withLabels.begin(); it != withLabels.end(); ++it)
-      {
-        labels.push_back(formatter.GenerateParameter(*it));
-      }
-
-      where.push_back(boost::lexical_cast<std::string>(withLabels.size()) +
-                      " = (SELECT COUNT(1) FROM Labels WHERE internalId = " + FormatLevel(queryLevel) +
-                      ".internalId AND label IN (" + Join(labels, "", ", ") + "))");
-    }
-    
-    if (!withoutLabels.empty())
+    if (!labels.empty())
     {
       /**
        * "In SQL Server, NOT EXISTS and NOT IN predicates are the best
@@ -405,14 +392,34 @@
        * question are NOT NULL."
        * https://explainextended.com/2009/09/15/not-in-vs-not-exists-vs-left-join-is-null-sql-server/
        **/
-      std::list<std::string> labels;
-      for (std::set<std::string>::const_iterator it = withoutLabels.begin(); it != withoutLabels.end(); ++it)
+
+      std::list<std::string> formattedLabels;
+      for (std::set<std::string>::const_iterator it = labels.begin(); it != labels.end(); ++it)
       {
-        labels.push_back(formatter.GenerateParameter(*it));
+        formattedLabels.push_back(formatter.GenerateParameter(*it));
       }
 
-      where.push_back("NOT EXISTS (SELECT 1 FROM Labels WHERE internalId = " + FormatLevel(queryLevel) +
-                      ".internalId AND label IN (" + Join(labels, "", ", ") + "))");
+      std::string condition;
+      switch (labelsConstraint)
+      {
+        case LabelsConstraint_Any:
+          condition = "> 0";
+          break;
+          
+        case LabelsConstraint_All:
+          condition = "= " + boost::lexical_cast<std::string>(labels.size());
+          break;
+          
+        case LabelsConstraint_None:
+          condition = "= 0";
+          break;
+          
+        default:
+          throw OrthancException(ErrorCode_ParameterOutOfRange);
+      }
+      
+      where.push_back("(SELECT COUNT(1) FROM Labels WHERE internalId = " + FormatLevel(queryLevel) +
+                      ".internalId AND label IN (" + Join(formattedLabels, "", ", ") + ")) " + condition);
     }
     
     where.push_back(FormatLevel(queryLevel) + ".resourceType = " +
--- a/Resources/Orthanc/Databases/ISqlLookupFormatter.h	Fri Apr 07 15:43:42 2023 +0200
+++ b/Resources/Orthanc/Databases/ISqlLookupFormatter.h	Fri Apr 07 22:32:15 2023 +0200
@@ -35,6 +35,13 @@
 {
   class DatabaseConstraint;
   
+  enum LabelsConstraint
+  {
+    LabelsConstraint_All,
+    LabelsConstraint_Any,
+    LabelsConstraint_None
+  };
+
   // This class is also used by the "orthanc-databases" project
   class ISqlLookupFormatter : public boost::noncopyable
   {
@@ -60,8 +67,8 @@
                       ISqlLookupFormatter& formatter,
                       const std::vector<DatabaseConstraint>& lookup,
                       ResourceType queryLevel,
-                      const std::set<std::string>& withLabels,     // New in Orthanc 1.12.0
-                      const std::set<std::string>& withoutLabels,  // New in Orthanc 1.12.0
+                      const std::set<std::string>& labels,  // New in Orthanc 1.12.0
+                      LabelsConstraint labelsConstraint,    // New in Orthanc 1.12.0
                       size_t limit);
   };
 }