# HG changeset patch # User Sebastien Jodogne # Date 1545325156 -3600 # Node ID 3f986ce336c8196d6b3a8ee482381d22576350d0 # Parent c7db469bbe8e4543a9d013736b988204b9d17780 working on Compatibility::DatabaseLookup diff -r c7db469bbe8e -r 3f986ce336c8 OrthancServer/SQLiteDatabaseWrapper.cpp --- 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(); diff -r c7db469bbe8e -r 3f986ce336c8 OrthancServer/Search/Compatibility/DatabaseLookup.cpp --- 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& patientsId, + { + static void ApplyLevel(SetOfResources& candidates, + const std::vector& lookup, + ResourceType level) + { + std::vector 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(i)); + + std::list 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& resourcesId, std::vector* instancesId, const std::vector& 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(level)); + + if (level != lowerLevel) + { + candidates.GoDown(); + } + } + + std::list resources; + candidates.Flatten(resources); + + // Climb up, up to queryLevel + + for (int level = lowerLevel; level > queryLevel; level--) + { + std::list parents; + for (std::list::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::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); + } + } + } } } } diff -r c7db469bbe8e -r 3f986ce336c8 OrthancServer/Search/Compatibility/DatabaseLookup.h --- 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& patientsId, + void ApplyLookupResources(std::vector& resourcesId, std::vector* instancesId, const std::vector& lookup, ResourceType queryLevel, diff -r c7db469bbe8e -r 3f986ce336c8 Plugins/Engine/OrthancPluginDatabase.cpp --- 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& patientsId, + void OrthancPluginDatabase::ApplyLookupResources(std::vector& resourcesId, std::vector* instancesId, const std::vector& lookup, ResourceType queryLevel, size_t limit) { Compatibility::DatabaseLookup compat(*this); - compat.ApplyLookupResources(patientsId, instancesId, lookup, queryLevel, limit); + compat.ApplyLookupResources(resourcesId, instancesId, lookup, queryLevel, limit); } diff -r c7db469bbe8e -r 3f986ce336c8 Plugins/Engine/OrthancPluginDatabase.h --- 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& patientsId, + virtual void ApplyLookupResources(std::vector& resourcesId, std::vector* instancesId, const std::vector& lookup, ResourceType queryLevel,