changeset 3053:3f986ce336c8 db-changes

working on Compatibility::DatabaseLookup
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 Dec 2018 17:59:16 +0100
parents c7db469bbe8e
children 3638de45a08c
files OrthancServer/SQLiteDatabaseWrapper.cpp OrthancServer/Search/Compatibility/DatabaseLookup.cpp OrthancServer/Search/Compatibility/DatabaseLookup.h Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h
diffstat 5 files changed, 149 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/SQLiteDatabaseWrapper.cpp	Thu Dec 20 16:58:52 2018 +0100
+++ b/OrthancServer/SQLiteDatabaseWrapper.cpp	Thu Dec 20 17:59:16 2018 +0100
@@ -1457,6 +1457,9 @@
       }
     }
     
+    assert(upperLevel <= queryLevel &&
+           queryLevel <= lowerLevel);
+
     {
       SQLite::Statement s(db_, SQLITE_FROM_HERE, "DROP TABLE IF EXISTS Lookup");
       s.Run();
--- a/OrthancServer/Search/Compatibility/DatabaseLookup.cpp	Thu Dec 20 16:58:52 2018 +0100
+++ b/OrthancServer/Search/Compatibility/DatabaseLookup.cpp	Thu Dec 20 17:59:16 2018 +0100
@@ -40,14 +40,153 @@
 namespace Orthanc
 {
   namespace Compatibility
-  {  
-    void DatabaseLookup::ApplyLookupResources(std::vector<std::string>& patientsId,
+  {
+    static void ApplyLevel(SetOfResources& candidates,
+                           const std::vector<DatabaseConstraint>& lookup,
+                           ResourceType level)
+    {
+      std::vector<DatabaseConstraint> identifiers;
+      
+      for (size_t i = 0; i < lookup.size(); i++)
+      {
+        if (lookup[i].GetLevel() == level &&
+            lookup[i].IsIdentifier())
+        {
+          identifiers.push_back(lookup[i]);
+        }
+      }
+    }
+
+
+    static std::string GetOneInstance(IDatabaseWrapper& database,
+                                      int64_t resource,
+                                      ResourceType level)
+    {
+      for (int i = level; i < ResourceType_Instance; i++)
+      {
+        assert(database.GetResourceType(resource) == static_cast<ResourceType>(i));
+
+        std::list<int64_t> children;
+        database.GetChildrenInternalId(children, resource);
+          
+        if (children.size() == 0)
+        {
+          throw OrthancException(ErrorCode_Database);
+        }
+          
+        resource = children.front();
+      }
+        
+      return database.GetPublicId(resource);
+    }
+                           
+
+    void DatabaseLookup::ApplyLookupResources(std::vector<std::string>& resourcesId,
                                               std::vector<std::string>* instancesId,
                                               const std::vector<DatabaseConstraint>& lookup,
                                               ResourceType queryLevel,
                                               size_t limit)
     {
-      throw OrthancException(ErrorCode_NotImplemented);
+      // This is a re-implementation of
+      // "../../../Resources/Graveyard/DatabaseOptimizations/LookupResource.cpp"
+
+      assert(ResourceType_Patient < ResourceType_Study &&
+             ResourceType_Study < ResourceType_Series &&
+             ResourceType_Series < ResourceType_Instance);
+    
+      ResourceType upperLevel = queryLevel;
+      ResourceType lowerLevel = queryLevel;
+
+      for (size_t i = 0; i < lookup.size(); i++)
+      {
+        ResourceType level = lookup[i].GetLevel();
+
+        if (level < upperLevel)
+        {
+          upperLevel = level;
+        }
+
+        if (level > lowerLevel)
+        {
+          lowerLevel = level;
+        }
+      }
+
+      assert(upperLevel <= queryLevel &&
+             queryLevel <= lowerLevel);
+
+      SetOfResources candidates(database_, upperLevel);
+
+      for (int level = upperLevel; level <= lowerLevel; level++)
+      {
+        ApplyLevel(candidates, lookup, static_cast<ResourceType>(level));
+
+        if (level != lowerLevel)
+        {
+          candidates.GoDown();
+        }
+      }
+
+      std::list<int64_t> resources;
+      candidates.Flatten(resources);
+
+      // Climb up, up to queryLevel
+
+      for (int level = lowerLevel; level > queryLevel; level--)
+      {
+        std::list<int64_t> parents;
+        for (std::list<int64_t>::const_iterator
+               it = resources.begin(); it != resources.end(); ++it)
+        {
+          int64_t parent;
+          if (database_.LookupParent(parent, *it))
+          {
+            parents.push_back(parent);
+          }
+        }
+
+        resources.swap(parents);
+      }
+
+      // Apply the limit, if given
+
+      if (limit != 0 &&
+          resources.size() > limit)
+      {
+        resources.resize(limit);
+      }
+
+      // Get the public ID of all the selected resources
+
+      resourcesId.resize(resources.size());
+
+      if (instancesId != NULL)
+      {
+        instancesId->resize(resources.size());
+      }
+
+      size_t pos = 0;
+
+      for (std::list<int64_t>::const_iterator
+             it = resources.begin(); it != resources.end(); ++it, pos++)
+      {
+        assert(database_.GetResourceType(*it) == queryLevel);
+
+        resourcesId[pos] = database_.GetPublicId(*it);
+
+        if (instancesId != NULL)
+        {
+          // Collect one child instance for each of the selected resources
+          if (queryLevel == ResourceType_Instance)
+          {
+            (*instancesId) [pos] = resourcesId[pos];
+          }
+          else
+          {
+            (*instancesId) [pos] = GetOneInstance(database_, *it, queryLevel);
+          }
+        }
+      }
     }
   }
 }
--- a/OrthancServer/Search/Compatibility/DatabaseLookup.h	Thu Dec 20 16:58:52 2018 +0100
+++ b/OrthancServer/Search/Compatibility/DatabaseLookup.h	Thu Dec 20 17:59:16 2018 +0100
@@ -50,7 +50,7 @@
       {
       }
 
-      void ApplyLookupResources(std::vector<std::string>& patientsId,
+      void ApplyLookupResources(std::vector<std::string>& resourcesId,
                                 std::vector<std::string>* instancesId,
                                 const std::vector<DatabaseConstraint>& lookup,
                                 ResourceType queryLevel,
--- a/Plugins/Engine/OrthancPluginDatabase.cpp	Thu Dec 20 16:58:52 2018 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.cpp	Thu Dec 20 17:59:16 2018 +0100
@@ -1111,14 +1111,14 @@
   }
 
 
-  void OrthancPluginDatabase::ApplyLookupResources(std::vector<std::string>& patientsId,
+  void OrthancPluginDatabase::ApplyLookupResources(std::vector<std::string>& resourcesId,
                                                    std::vector<std::string>* instancesId,
                                                    const std::vector<DatabaseConstraint>& lookup,
                                                    ResourceType queryLevel,
                                                    size_t limit)
   {
     Compatibility::DatabaseLookup compat(*this);
-    compat.ApplyLookupResources(patientsId, instancesId, lookup, queryLevel, limit);
+    compat.ApplyLookupResources(resourcesId, instancesId, lookup, queryLevel, limit);
   }
 
 
--- a/Plugins/Engine/OrthancPluginDatabase.h	Thu Dec 20 16:58:52 2018 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.h	Thu Dec 20 17:59:16 2018 +0100
@@ -311,7 +311,7 @@
     virtual bool IsDiskSizeAbove(uint64_t threshold) 
       ORTHANC_OVERRIDE;
 
-    virtual void ApplyLookupResources(std::vector<std::string>& patientsId,
+    virtual void ApplyLookupResources(std::vector<std::string>& resourcesId,
                                       std::vector<std::string>* instancesId,
                                       const std::vector<DatabaseConstraint>& lookup,
                                       ResourceType queryLevel,