# HG changeset patch # User Sebastien Jodogne # Date 1545221284 -3600 # Node ID 18a2d196414b8d7c31c896ddd55c5f5b5c705842 # Parent 25afa7b8cb51969b922b412f96f342407a487ff6 simplification diff -r 25afa7b8cb51 -r 18a2d196414b OrthancServer/IDatabaseWrapper.h --- 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& patientsId, - std::vector& instancesId, - const std::vector& lookup, - size_t limit) = 0; - virtual void ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, const std::vector& lookup, diff -r 25afa7b8cb51 -r 18a2d196414b OrthancServer/SQLiteDatabaseWrapper.cpp --- 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(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(constraint.GetTag().GetGroup()) + - " AND " + tag + ".tagElement = " + - boost::lexical_cast(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(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(constraint.GetTag().GetGroup()) + + " AND " + tag + ".tagElement = " + + boost::lexical_cast(constraint.GetTag().GetElement())); } - + static void AnswerLookup(std::vector& resourcesId, std::vector& instancesId, @@ -1488,76 +1497,18 @@ } - static void FormatConstraints(std::string& joins, - std::string& comparisons, - std::vector& parameters, - const std::vector& 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& patientsId, - std::vector& instancesId, - const std::vector& lookup, - size_t limit) - { - PrepareLookup(db_); - - std::string joins, comparisons; - std::vector 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(ResourceType_Patient) + comparisons); - - if (limit != 0) - { - sql += " LIMIT " + boost::lexical_cast(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& resourcesId, std::vector& instancesId, const std::vector& 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 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(level - 1)) + " ON " + + FormatLevel(static_cast(level)) + " ON " + FormatLevel(static_cast(level - 1)) + ".internalId=" + FormatLevel(static_cast(level)) + ".parentId"); } diff -r 25afa7b8cb51 -r 18a2d196414b OrthancServer/SQLiteDatabaseWrapper.h --- 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& patientsId, - std::vector& instancesId, - const std::vector& lookup, - size_t limit); - virtual void ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, const std::vector& lookup, diff -r 25afa7b8cb51 -r 18a2d196414b OrthancServer/ServerContext.cpp --- 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 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 diff -r 25afa7b8cb51 -r 18a2d196414b OrthancServer/ServerIndex.cpp --- 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& patientsId, - std::vector& instancesId, - const DatabaseLookup& lookup, - size_t limit) - { - std::vector normalized; - NormalizeLookup(normalized, lookup, ResourceType_Patient); - - { - boost::mutex::scoped_lock lock(mutex_); - db_.ApplyLookupPatients(patientsId, instancesId, normalized, limit); - } - } - - void ServerIndex::ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, const DatabaseLookup& lookup, diff -r 25afa7b8cb51 -r 18a2d196414b OrthancServer/ServerIndex.h --- 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& patientsId, - std::vector& instancesId, - const DatabaseLookup& lookup, - size_t limit); - void ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, const DatabaseLookup& lookup, diff -r 25afa7b8cb51 -r 18a2d196414b Plugins/Engine/OrthancPluginDatabase.cpp --- 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& patientsId, - std::vector& instancesId, - const std::vector& lookup, - size_t limit) - { - throw OrthancException(ErrorCode_NotImplemented); - } - - void OrthancPluginDatabase::ApplyLookupResources(std::vector& patientsId, std::vector& instancesId, const std::vector& lookup, diff -r 25afa7b8cb51 -r 18a2d196414b Plugins/Engine/OrthancPluginDatabase.h --- 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& patientsId, - std::vector& instancesId, - const std::vector& lookup, - size_t limit); - virtual void ApplyLookupResources(std::vector& patientsId, std::vector& instancesId, const std::vector& lookup,