changeset 3031:18a2d196414b db-changes

simplification
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 19 Dec 2018 13:08:04 +0100
parents 25afa7b8cb51
children 19ebb606910d
files OrthancServer/IDatabaseWrapper.h OrthancServer/SQLiteDatabaseWrapper.cpp OrthancServer/SQLiteDatabaseWrapper.h OrthancServer/ServerContext.cpp OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h
diffstat 8 files changed, 137 insertions(+), 216 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/IDatabaseWrapper.h	Wed Dec 19 11:18:39 2018 +0100
+++ b/OrthancServer/IDatabaseWrapper.h	Wed Dec 19 13:08:04 2018 +0100
@@ -227,11 +227,6 @@
 
     virtual bool IsDiskSizeAbove(uint64_t threshold) = 0;
 
-    virtual void ApplyLookupPatients(std::vector<std::string>& patientsId,
-                                     std::vector<std::string>& instancesId,
-                                     const std::vector<DatabaseConstraint>& lookup,
-                                     size_t limit) = 0;
-
     virtual void ApplyLookupResources(std::vector<std::string>& resourcesId,
                                       std::vector<std::string>& instancesId,
                                       const std::vector<DatabaseConstraint>& lookup,
--- a/OrthancServer/SQLiteDatabaseWrapper.cpp	Wed Dec 19 11:18:39 2018 +0100
+++ b/OrthancServer/SQLiteDatabaseWrapper.cpp	Wed Dec 19 13:08:04 2018 +0100
@@ -1228,38 +1228,6 @@
   }      
   
 
-  static void FormatJoin(std::string& target,
-                         const DatabaseConstraint& constraint,
-                         size_t index)
-  {
-    std::string tag = "t" + boost::lexical_cast<std::string>(index);
-
-    if (constraint.IsMandatory())
-    {
-      target = " INNER JOIN ";
-    }
-    else
-    {
-      target = " LEFT JOIN ";
-    }
-
-    if (constraint.IsIdentifier())
-    {
-      target += "DicomIdentifiers ";
-    }
-    else
-    {
-      target += "MainDicomTags ";
-    }
-
-    target += (tag + " ON " + tag + ".id = " + FormatLevel(constraint.GetLevel()) +
-               ".internalId AND " + tag + ".tagGroup = " +
-               boost::lexical_cast<std::string>(constraint.GetTag().GetGroup()) +
-               " AND " + tag + ".tagElement = " +
-               boost::lexical_cast<std::string>(constraint.GetTag().GetElement()));
-  }
-  
-
   static bool FormatComparison(std::string& target,
                                const DatabaseConstraint& constraint,
                                size_t index,
@@ -1344,46 +1312,58 @@
       case ConstraintType_Wildcard:
       {
         const std::string value = constraint.GetSingleValue();
-        std::string escaped;
-        escaped.reserve(value.size());
 
-        for (size_t i = 0; i < value.size(); i++)
+        if (value == "*")
         {
-          if (value[i] == '*')
+          if (!constraint.IsMandatory())
           {
-            escaped += "%";
+            // Universal constraint on an optional tag, ignore it
+            return false;
           }
-          else if (value[i] == '?')
+        }
+        else
+        {
+          std::string escaped;
+          escaped.reserve(value.size());
+
+          for (size_t i = 0; i < value.size(); i++)
           {
-            escaped += "_";
-          }
-          else if (value[i] == '%')
-          {
-            escaped += "\\%";
+            if (value[i] == '*')
+            {
+              escaped += "%";
+            }
+            else if (value[i] == '?')
+            {
+              escaped += "_";
+            }
+            else if (value[i] == '%')
+            {
+              escaped += "\\%";
+            }
+            else if (value[i] == '_')
+            {
+              escaped += "\\_";
+            }
+            else if (value[i] == '\\')
+            {
+              escaped += "\\\\";
+            }
+            else
+            {
+              escaped += value[i];
+            }               
           }
-          else if (value[i] == '_')
+
+          parameters.push_back(escaped);
+
+          if (constraint.IsCaseSensitive())
           {
-            escaped += "\\_";
-          }
-          else if (value[i] == '\\')
-          {
-            escaped += "\\\\";
+            comparison = tag + ".value LIKE ? ESCAPE '\\'";
           }
           else
           {
-            escaped += value[i];
-          }               
-        }
-
-        parameters.push_back(escaped);
-
-        if (constraint.IsCaseSensitive())
-        {
-          comparison = tag + ".value LIKE ? ESCAPE '\\'";
-        }
-        else
-        {
-          comparison = "lower(" + tag + ".value) LIKE lower(?) ESCAPE '\\'";
+            comparison = "lower(" + tag + ".value) LIKE lower(?) ESCAPE '\\'";
+          }
         }
           
         break;
@@ -1396,23 +1376,52 @@
 
     if (constraint.IsMandatory())
     {
-      target += comparison;
+      target = comparison;
+    }
+    else if (comparison.empty())
+    {
+      target = tag + ".value IS NULL";
     }
     else
     {
-      target += tag + ".value IS NULL OR " + comparison;
+      target = tag + ".value IS NULL OR " + comparison;
     }
 
     return true;
   }
 
 
-  static void PrepareLookup(SQLite::Connection& db)
+  static void FormatJoin(std::string& target,
+                         const DatabaseConstraint& constraint,
+                         size_t index)
   {
-    SQLite::Statement s(db, SQLITE_FROM_HERE, "DROP TABLE IF EXISTS Lookup");
-    s.Run();
+    std::string tag = "t" + boost::lexical_cast<std::string>(index);
+
+    if (constraint.IsMandatory())
+    {
+      target = " INNER JOIN ";
+    }
+    else
+    {
+      target = " LEFT JOIN ";
+    }
+
+    if (constraint.IsIdentifier())
+    {
+      target += "DicomIdentifiers ";
+    }
+    else
+    {
+      target += "MainDicomTags ";
+    }
+
+    target += (tag + " ON " + tag + ".id = " + FormatLevel(constraint.GetLevel()) +
+               ".internalId AND " + tag + ".tagGroup = " +
+               boost::lexical_cast<std::string>(constraint.GetTag().GetGroup()) +
+               " AND " + tag + ".tagElement = " +
+               boost::lexical_cast<std::string>(constraint.GetTag().GetElement()));
   }
-
+  
 
   static void AnswerLookup(std::vector<std::string>& resourcesId,
                            std::vector<std::string>& instancesId,
@@ -1488,76 +1497,18 @@
   }
 
 
-  static void FormatConstraints(std::string& joins,
-                                std::string& comparisons,
-                                std::vector<std::string>& parameters,
-                                const std::vector<DatabaseConstraint>& lookup)
-  {
-    size_t count = 0;
-    
-    for (size_t i = 0; i < lookup.size(); i++)
-    {
-      std::string comparison;
-      
-      if (FormatComparison(comparison, lookup[i], count, parameters))
-      {
-        std::string join;
-        FormatJoin(join, lookup[i], count);
-        joins += join;
-
-        comparisons += " AND (" + comparison + ")";
-        
-        count ++;
-      }
-    }
-  }
-                                
-  
-  
-  void SQLiteDatabaseWrapper::ApplyLookupPatients(std::vector<std::string>& patientsId,
-                                                  std::vector<std::string>& instancesId,
-                                                  const std::vector<DatabaseConstraint>& lookup,
-                                                  size_t limit)
-  {
-    PrepareLookup(db_);
-    
-    std::string joins, comparisons;
-    std::vector<std::string> parameters;
-    FormatConstraints(joins, comparisons, parameters, lookup);
-
-    {
-      std::string sql = ("CREATE TEMPORARY TABLE Lookup AS "
-                         "SELECT patients.publicId, patients.internalId FROM Resources AS patients" +
-                         joins + " WHERE patients.resourceType = " +
-                         boost::lexical_cast<std::string>(ResourceType_Patient) + comparisons);
-
-      if (limit != 0)
-      {
-        sql += " LIMIT " + boost::lexical_cast<std::string>(limit);
-      }
-
-      printf("[%s]\n", sql.c_str());
-
-      SQLite::Statement s(db_, sql);
-
-      for (size_t i = 0; i < parameters.size(); i++)
-      {
-        s.BindString(i, parameters[i]);
-      }
-
-      s.Run();
-    }
-
-    AnswerLookup(patientsId, instancesId, db_, ResourceType_Patient);
-  }
-
-
   void SQLiteDatabaseWrapper::ApplyLookupResources(std::vector<std::string>& resourcesId,
                                                    std::vector<std::string>& instancesId,
                                                    const std::vector<DatabaseConstraint>& lookup,
                                                    ResourceType queryLevel,
                                                    size_t limit)
   {
+    for (size_t i = 0; i < lookup.size(); i++)
+    {
+      std::cout << i << ": " << lookup[i].GetTag() << " - " << EnumerationToString(lookup[i].GetLevel());
+      std::cout << std::endl;
+    }
+    
     assert(ResourceType_Patient < ResourceType_Study &&
            ResourceType_Study < ResourceType_Series &&
            ResourceType_Series < ResourceType_Instance);
@@ -1582,11 +1533,34 @@
     
     printf("ICI 2: [%s] -> [%s]\n", EnumerationToString(upperLevel), EnumerationToString(lowerLevel));
     
-    PrepareLookup(db_);
+    {
+      SQLite::Statement s(db_, SQLITE_FROM_HERE, "DROP TABLE IF EXISTS Lookup");
+      s.Run();
+    }
     
     std::string joins, comparisons;
     std::vector<std::string> parameters;
-    FormatConstraints(joins, comparisons, parameters, lookup);
+
+    size_t count = 0;
+    
+    for (size_t i = 0; i < lookup.size(); i++)
+    {
+      std::string comparison;
+      
+      if (FormatComparison(comparison, lookup[i], count, parameters))
+      {
+        std::string join;
+        FormatJoin(join, lookup[i], count);
+        joins += join;
+
+        if (!comparison.empty())
+        {
+          comparisons += " AND " + comparison;
+        }
+        
+        count ++;
+      }
+    }
 
     {
       std::string sql = ("CREATE TEMPORARY TABLE Lookup AS SELECT " +
@@ -1605,7 +1579,7 @@
       for (int level = queryLevel + 1; level <= lowerLevel; level++)
       {
         sql += (" INNER JOIN Resources " +
-                FormatLevel(static_cast<ResourceType>(level - 1)) + " ON " +
+                FormatLevel(static_cast<ResourceType>(level)) + " ON " +
                 FormatLevel(static_cast<ResourceType>(level - 1)) + ".internalId=" +
                 FormatLevel(static_cast<ResourceType>(level)) + ".parentId");
       }
--- a/OrthancServer/SQLiteDatabaseWrapper.h	Wed Dec 19 11:18:39 2018 +0100
+++ b/OrthancServer/SQLiteDatabaseWrapper.h	Wed Dec 19 13:08:04 2018 +0100
@@ -277,11 +277,6 @@
 
     virtual bool IsDiskSizeAbove(uint64_t threshold);
 
-    virtual void ApplyLookupPatients(std::vector<std::string>& patientsId,
-                                     std::vector<std::string>& instancesId,
-                                     const std::vector<DatabaseConstraint>& lookup,
-                                     size_t limit);
-
     virtual void ApplyLookupResources(std::vector<std::string>& resourcesId,
                                       std::vector<std::string>& instancesId,
                                       const std::vector<DatabaseConstraint>& lookup,
--- a/OrthancServer/ServerContext.cpp	Wed Dec 19 11:18:39 2018 +0100
+++ b/OrthancServer/ServerContext.cpp	Wed Dec 19 13:08:04 2018 +0100
@@ -780,6 +780,7 @@
                             size_t limit)
   {
     LookupMode mode;
+    unsigned int databaseLimit;
       
     {
       // New configuration option in 1.5.1
@@ -805,6 +806,15 @@
                                "Configuration option \"StorageAccessOnFind\" "
                                "should be \"Always\", \"Never\" or \"Answers\": " + value);
       }
+
+      if (lookup.GetLevel() == ResourceType_Instance)
+      {
+        databaseLimit = lock.GetConfiguration().GetUnsignedIntegerParameter("LimitFindInstances", 0);
+      }
+      else
+      {
+        databaseLimit = lock.GetConfiguration().GetUnsignedIntegerParameter("LimitFindResults", 0);
+      }
     }      
 
 
@@ -817,20 +827,11 @@
     {
       std::vector<std::string> resources2, instances2;
 
-      size_t lookupLimit = (limit == 0 ? 0 : limit + 1);
-      
-      if (lookup.GetLevel() == ResourceType_Patient)
-      {
-        GetIndex().ApplyLookupPatients(resources2, instances2, lookup2, lookupLimit);
-      }
-      else
-      {
-        GetIndex().ApplyLookupResources(resources2, instances2, lookup2,
-                                        lookup.GetLevel(), lookupLimit);
-      }
+      size_t lookupLimit = (databaseLimit == 0 ? 0 : databaseLimit + 1);      
+      GetIndex().ApplyLookupResources(resources2, instances2, lookup2, lookup.GetLevel(), lookupLimit);
 
-      if (limit != 0 &&
-          resources2.size() > limit)
+      if (databaseLimit != 0 &&
+          resources2.size() > databaseLimit)
       {
         complete = false;
       }
@@ -843,12 +844,12 @@
       }
 
       printf("%d %d\n", resources2.size(), resources.size());
-      /*assert(resources2.size() >= resources.size());
+      assert(resources2.size() >= resources.size());
       
       for (size_t i = 0; i < resources.size(); i++)
       {
         assert(r.find(resources[i]) != r.end());
-        }*/
+      }
     }
 #endif
     
--- a/OrthancServer/ServerIndex.cpp	Wed Dec 19 11:18:39 2018 +0100
+++ b/OrthancServer/ServerIndex.cpp	Wed Dec 19 13:08:04 2018 +0100
@@ -2565,56 +2565,31 @@
 
     target.clear();
     target.reserve(source.GetConstraintsCount());
-    
+
     for (size_t i = 0; i < source.GetConstraintsCount(); i++)
     {
-      const DicomTagConstraint& constraint = source.GetConstraint(i);
+      ResourceType level;
+      DicomTagType type;
       
-      ResourceType tagLevel;
-      DicomTagType tagType;
-      mainDicomTagsRegistry_->LookupTag(tagLevel, tagType, constraint.GetTag());
-
-      if (//IsResourceLevelAboveOrEqual(tagLevel, queryLevel) &&
-          (tagType == DicomTagType_Identifier ||
-           tagType == DicomTagType_Main))
+      mainDicomTagsRegistry_->LookupTag(level, type, source.GetConstraint(i).GetTag());
+
+      if (type == DicomTagType_Identifier ||
+          type == DicomTagType_Main)
       {
         // Use the fact that patient-level tags are copied at the study level
-        if (queryLevel != ResourceType_Patient &&
-            tagLevel == ResourceType_Patient)
+        if (level == ResourceType_Patient &&
+            queryLevel != ResourceType_Patient)
         {
-          tagLevel = ResourceType_Study;
+          level = ResourceType_Study;
         }
         
-        DatabaseConstraint c(constraint, tagLevel, tagType);
-
-        // Avoid universal constraints
-        if (!(c.GetConstraintType() == ConstraintType_Equal &&
-              c.GetSingleValue() == "") &&
-            !(c.GetConstraintType() == ConstraintType_Wildcard &&
-              c.GetSingleValue() == "*"))
-        {
-          target.push_back(c);
-        }
+        DatabaseConstraint c(source.GetConstraint(i), level, type);
+        target.push_back(c);
       }
     }
   }
 
 
-  void ServerIndex::ApplyLookupPatients(std::vector<std::string>& patientsId,
-                                        std::vector<std::string>& instancesId,
-                                        const DatabaseLookup& lookup,
-                                        size_t limit)
-  {
-    std::vector<DatabaseConstraint> normalized;
-    NormalizeLookup(normalized, lookup, ResourceType_Patient);
-
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      db_.ApplyLookupPatients(patientsId, instancesId, normalized, limit);
-    }
-  }
-
-  
   void ServerIndex::ApplyLookupResources(std::vector<std::string>& resourcesId,
                                          std::vector<std::string>& instancesId,
                                          const DatabaseLookup& lookup,
--- a/OrthancServer/ServerIndex.h	Wed Dec 19 11:18:39 2018 +0100
+++ b/OrthancServer/ServerIndex.h	Wed Dec 19 13:08:04 2018 +0100
@@ -299,11 +299,6 @@
 
     void ReconstructInstance(ParsedDicomFile& dicom);
 
-    void ApplyLookupPatients(std::vector<std::string>& patientsId,
-                             std::vector<std::string>& instancesId,
-                             const DatabaseLookup& lookup,
-                             size_t limit);
-
     void ApplyLookupResources(std::vector<std::string>& resourcesId,
                               std::vector<std::string>& instancesId,
                               const DatabaseLookup& lookup,
--- a/Plugins/Engine/OrthancPluginDatabase.cpp	Wed Dec 19 11:18:39 2018 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.cpp	Wed Dec 19 13:08:04 2018 +0100
@@ -1162,15 +1162,6 @@
   }
 
 
-  void OrthancPluginDatabase::ApplyLookupPatients(std::vector<std::string>& patientsId,
-                                                  std::vector<std::string>& instancesId,
-                                                  const std::vector<DatabaseConstraint>& lookup,
-                                                  size_t limit)
-  {
-    throw OrthancException(ErrorCode_NotImplemented);
-  }
-  
-
   void OrthancPluginDatabase::ApplyLookupResources(std::vector<std::string>& patientsId,
                                                    std::vector<std::string>& instancesId,
                                                    const std::vector<DatabaseConstraint>& lookup,
--- a/Plugins/Engine/OrthancPluginDatabase.h	Wed Dec 19 11:18:39 2018 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.h	Wed Dec 19 13:08:04 2018 +0100
@@ -271,11 +271,6 @@
 
     virtual bool IsDiskSizeAbove(uint64_t threshold);
 
-    virtual void ApplyLookupPatients(std::vector<std::string>& patientsId,
-                                     std::vector<std::string>& instancesId,
-                                     const std::vector<DatabaseConstraint>& lookup,
-                                     size_t limit);
-
     virtual void ApplyLookupResources(std::vector<std::string>& patientsId,
                                       std::vector<std::string>& instancesId,
                                       const std::vector<DatabaseConstraint>& lookup,