# HG changeset patch # User Sebastien Jodogne # Date 1545155815 -3600 # Node ID ea653ec47f31de004331ee2af242607feadb19ac # Parent fd587cf51a89eb5c61f4139fe8ee93f08b1293e2 new class: DatabaseConstraint diff -r fd587cf51a89 -r ea653ec47f31 CMakeLists.txt --- a/CMakeLists.txt Tue Dec 18 12:50:27 2018 +0100 +++ b/CMakeLists.txt Tue Dec 18 18:56:55 2018 +0100 @@ -71,6 +71,7 @@ OrthancServer/OrthancRestApi/OrthancRestResources.cpp OrthancServer/OrthancRestApi/OrthancRestSystem.cpp OrthancServer/QueryRetrieveHandler.cpp + OrthancServer/Search/DatabaseConstraint.cpp OrthancServer/Search/DatabaseLookup.cpp OrthancServer/Search/DicomTagConstraint.cpp OrthancServer/Search/HierarchicalMatcher.cpp diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/IDatabaseWrapper.h --- a/OrthancServer/IDatabaseWrapper.h Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/IDatabaseWrapper.h Tue Dec 18 18:56:55 2018 +0100 @@ -40,6 +40,7 @@ #include "ExportedResource.h" #include "IDatabaseListener.h" +#include "Search/DatabaseConstraint.h" #include "Search/DatabaseLookup.h" #include @@ -228,12 +229,12 @@ virtual void ApplyLookupPatients(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, size_t limit) = 0; virtual void ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, ResourceType queryLevel, size_t limit) = 0; }; diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/SQLiteDatabaseWrapper.cpp --- a/OrthancServer/SQLiteDatabaseWrapper.cpp Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/SQLiteDatabaseWrapper.cpp Tue Dec 18 18:56:55 2018 +0100 @@ -1206,9 +1206,211 @@ } + 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 = "; + + switch (constraint.GetLevel()) + { + case ResourceType_Patient: + target += "patient"; + break; + + case ResourceType_Study: + target += "study"; + break; + + case ResourceType_Series: + target += "series"; + break; + + case ResourceType_Instance: + target += "instance"; + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + target += (".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, + std::vector& parameters) + { + std::string tag = "t" + boost::lexical_cast(index); + + std::string comparison; + + switch (constraint.GetConstraintType()) + { + case ConstraintType_Equal: + case ConstraintType_SmallerOrEqual: + case ConstraintType_GreaterOrEqual: + { + std::string op; + switch (constraint.GetConstraintType()) + { + case ConstraintType_Equal: + op = "="; + break; + + case ConstraintType_SmallerOrEqual: + op = "<="; + break; + + case ConstraintType_GreaterOrEqual: + op = ">="; + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + parameters.push_back(constraint.GetSingleValue()); + + if (constraint.IsCaseSensitive()) + { + comparison = tag + ".value " + op + " ?"; + } + else + { + comparison = "lower(" + tag + ".value) " + op + " lower(?)"; + } + + break; + } + + case ConstraintType_List: + { + for (size_t i = 0; i < constraint.GetValuesCount(); i++) + { + parameters.push_back(constraint.GetValue(i)); + + if (!comparison.empty()) + { + comparison += ", "; + } + + if (constraint.IsCaseSensitive()) + { + comparison += "?"; + } + else + { + comparison += "lower(?)"; + } + } + + if (constraint.IsCaseSensitive()) + { + comparison = tag + ".value IN (" + comparison + ")"; + } + else + { + comparison = "lower(" + tag + ".value) IN (" + comparison + ")"; + } + + break; + } + + 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[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]; + } + } + + parameters.push_back(escaped); + + if (constraint.IsCaseSensitive()) + { + comparison = tag + ".value LIKE ? ESCAPE '\\'"; + } + else + { + comparison = "lower(" + tag + ".value) LIKE lower(?) ESCAPE '\\'"; + } + + break; + } + + default: + // Don't modify "parameters"! + return false; + } + + if (constraint.IsMandatory()) + { + target += comparison; + } + else + { + target += tag + ".value IS NULL OR " + comparison; + } + + return true; + } + + void SQLiteDatabaseWrapper::ApplyLookupPatients(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, size_t limit) { printf("ICI 1\n"); @@ -1218,132 +1420,37 @@ s.Run(); } - std::string heading = "CREATE TEMPORARY TABLE Lookup AS SELECT patient.publicId, patient.internalId FROM Resources AS patient "; - std::string trailer; + std::string joins, comparisons; std::vector parameters; - for (size_t i = 0; i < lookup.GetConstraintsCount(); i++) + size_t count = 0; + + for (size_t i = 0; i < lookup.size(); i++) { - const DicomTagConstraint& constraint = lookup.GetConstraint(i); - - if (constraint.GetTagType() != DicomTagType_Identifier && - constraint.GetTagType() != DicomTagType_Main) - { - // This should have been set by ServerIndex::NormalizeLookup()" - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } + std::string comparison; - std::string tag = "t" + boost::lexical_cast(i); - - char on[128]; - sprintf( - on, "%s JOIN %s %s ON %s.id = patient.internalId AND %s.tagGroup = 0x%04x AND %s.tagElement = 0x%04x ", - constraint.IsMandatory() ? "INNER" : "LEFT", - constraint.GetTagType() == DicomTagType_Identifier ? "DicomIdentifiers" : "MainDicomTags", - tag.c_str(), tag.c_str(), tag.c_str(), constraint.GetTag().GetGroup(), - tag.c_str(), constraint.GetTag().GetElement()); - - std::string comparison; - - switch (constraint.GetConstraintType()) + if (FormatComparison(comparison, lookup[i], count, parameters)) { - case ConstraintType_Equal: - case ConstraintType_SmallerOrEqual: - case ConstraintType_GreaterOrEqual: - { - std::string op; - switch (constraint.GetConstraintType()) - { - case ConstraintType_Equal: - op = "="; - break; - - case ConstraintType_SmallerOrEqual: - op = "<="; - break; - - case ConstraintType_GreaterOrEqual: - op = ">="; - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - - parameters.push_back(constraint.GetValue()); - - if (constraint.IsCaseSensitive()) - { - comparison = tag + ".value " + op + " ?"; - } - else - { - comparison = "lower(" + tag + ".value) " + op + " lower(?)"; - } + std::string join; + FormatJoin(join, lookup[i], count); + joins += join; - break; - } - - case ConstraintType_List: - for (std::set::const_iterator - it = constraint.GetValues().begin(); - it != constraint.GetValues().end(); ++it) - { - parameters.push_back(*it); - - if (!comparison.empty()) - { - comparison += ", "; - } - - if (constraint.IsCaseSensitive()) - { - comparison += "?"; - } - else - { - comparison += "lower(?)"; - } - } - - if (constraint.IsCaseSensitive()) - { - comparison = tag + ".value IN (" + comparison + ")"; - } - else - { - comparison = "lower(" + tag + ".value) IN (" + comparison + ")"; - } - - break; - - //case ConstraintType_Wildcard: - //break; - - default: - continue; + comparisons += " AND (" + comparison + ")"; + + count ++; } - - heading += std::string(on); - - trailer += "AND ("; - - if (!constraint.IsMandatory()) - { - trailer += tag + ".value IS NULL OR "; - } - - trailer += comparison + ") "; - } - - if (limit != 0) - { - trailer += " LIMIT " + boost::lexical_cast(limit); } { - std::string sql = (heading + "WHERE patient.resourceType = " + - boost::lexical_cast(ResourceType_Patient) + " " + trailer); + std::string sql = ("CREATE TEMPORARY TABLE Lookup AS " + "SELECT patient.publicId, patient.internalId FROM Resources AS patient" + + joins + " WHERE patient.resourceType = " + + boost::lexical_cast(ResourceType_Patient) + comparisons); + + if (limit != 0) + { + sql += " LIMIT " + boost::lexical_cast(limit); + } printf("[%s]\n", sql.c_str()); @@ -1377,18 +1484,32 @@ printf("** [%s] [%s]\n", patient.c_str(), instance.c_str()); } } - - throw OrthancException(ErrorCode_NotImplemented); } void SQLiteDatabaseWrapper::ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, ResourceType queryLevel, size_t limit) { - printf("ICI 2\n"); + ResourceType upperLevel = queryLevel; + ResourceType lowerLevel = queryLevel; + + for (size_t i = 0; i < lookup.size(); i++) + { + if (!IsResourceLevelAboveOrEqual(upperLevel, lookup[i].GetLevel())) + { + upperLevel = lookup[i].GetLevel(); + } + + if (!IsResourceLevelAboveOrEqual(lookup[i].GetLevel(), lowerLevel)) + { + lowerLevel = lookup[i].GetLevel(); + } + } + + printf("ICI 2: [%s] -> [%s]\n", EnumerationToString(upperLevel), EnumerationToString(lowerLevel)); throw OrthancException(ErrorCode_NotImplemented); } diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/SQLiteDatabaseWrapper.h --- a/OrthancServer/SQLiteDatabaseWrapper.h Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/SQLiteDatabaseWrapper.h Tue Dec 18 18:56:55 2018 +0100 @@ -279,12 +279,12 @@ virtual void ApplyLookupPatients(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, size_t limit); virtual void ApplyLookupResources(std::vector& resourcesId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, ResourceType queryLevel, size_t limit); }; diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/Search/DatabaseConstraint.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Search/DatabaseConstraint.cpp Tue Dec 18 18:56:55 2018 +0100 @@ -0,0 +1,108 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "../PrecompiledHeadersServer.h" +#include "DatabaseConstraint.h" + +#include "../../Core/OrthancException.h" +#include "../ServerToolbox.h" + +namespace Orthanc +{ + DatabaseConstraint::DatabaseConstraint(const DicomTagConstraint& constraint, + ResourceType level, + DicomTagType tagType) : + level_(level), + tag_(constraint.GetTag()), + constraintType_(constraint.GetConstraintType()), + mandatory_(constraint.IsMandatory()) + { + switch (tagType) + { + case DicomTagType_Identifier: + isIdentifier_ = true; + caseSensitive_ = true; + break; + + case DicomTagType_Main: + isIdentifier_ = false; + caseSensitive_ = constraint.IsCaseSensitive(); + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + values_.reserve(constraint.GetValues().size()); + + for (std::set::const_iterator + it = constraint.GetValues().begin(); + it != constraint.GetValues().end(); ++it) + { + if (isIdentifier_) + { + values_.push_back(ServerToolbox::NormalizeIdentifier(*it)); + } + else + { + values_.push_back(*it); + } + } + } + + + const std::string& DatabaseConstraint::GetValue(size_t index) const + { + if (index >= values_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + return values_[index]; + } + } + + + const std::string& DatabaseConstraint::GetSingleValue() const + { + if (values_.size() != 1) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return values_[0]; + } + } +} diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/Search/DatabaseConstraint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Search/DatabaseConstraint.h Tue Dec 18 18:56:55 2018 +0100 @@ -0,0 +1,95 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "DicomTagConstraint.h" + +namespace Orthanc +{ + class DatabaseConstraint + { + private: + ResourceType level_; + DicomTag tag_; + bool isIdentifier_; + ConstraintType constraintType_; + std::vector values_; + bool caseSensitive_; + bool mandatory_; + + public: + DatabaseConstraint(const DicomTagConstraint& constraint, + ResourceType level, + DicomTagType tagType); + + ResourceType GetLevel() const + { + return level_; + } + + const DicomTag& GetTag() const + { + return tag_; + } + + bool IsIdentifier() const + { + return isIdentifier_; + } + + ConstraintType GetConstraintType() const + { + return constraintType_; + } + + size_t GetValuesCount() const + { + return values_.size(); + } + + const std::string& GetValue(size_t index) const; + + const std::string& GetSingleValue() const; + + bool IsCaseSensitive() const + { + return caseSensitive_; + } + + bool IsMandatory() const + { + return mandatory_; + } + }; +} diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/Search/DicomTagConstraint.cpp --- a/OrthancServer/Search/DicomTagConstraint.cpp Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/Search/DicomTagConstraint.cpp Tue Dec 18 18:56:55 2018 +0100 @@ -100,7 +100,6 @@ bool caseSensitive, bool mandatory) : tag_(tag), - tagType_(DicomTagType_Generic), constraintType_(type), caseSensitive_(caseSensitive), mandatory_(mandatory) @@ -131,7 +130,6 @@ bool caseSensitive, bool mandatory) : tag_(tag), - tagType_(DicomTagType_Generic), constraintType_(type), caseSensitive_(caseSensitive), mandatory_(mandatory) @@ -143,20 +141,6 @@ } - DicomTagConstraint* DicomTagConstraint::Clone() const - { - std::auto_ptr clone(new DicomTagConstraint); - - clone->tag_ = tag_; - clone->constraintType_ = constraintType_; - clone->values_ = values_; - clone->caseSensitive_ = caseSensitive_; - clone->mandatory_ = mandatory_; - - return clone.release(); - } - - void DicomTagConstraint::AddValue(const std::string& value) { if (constraintType_ != ConstraintType_List) diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/Search/DicomTagConstraint.h --- a/OrthancServer/Search/DicomTagConstraint.h Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/Search/DicomTagConstraint.h Tue Dec 18 18:56:55 2018 +0100 @@ -47,7 +47,6 @@ class RegularExpression; DicomTag tag_; - DicomTagType tagType_; ConstraintType constraintType_; std::set values_; bool caseSensitive_; @@ -55,12 +54,6 @@ boost::shared_ptr regex_; - DicomTagConstraint() : - tag_(0, 0), - tagType_(DicomTagType_Generic) - { - } - public: DicomTagConstraint(const DicomTag& tag, ConstraintType type, @@ -74,24 +67,11 @@ bool caseSensitive, bool mandatory); - DicomTagConstraint* Clone() const; - const DicomTag& GetTag() const { return tag_; } - DicomTagType GetTagType() const - { - return tagType_; - } - - // Set by "ServerIndex::NormalizeLookup()" - void SetTagType(DicomTagType type) - { - tagType_ = type; - } - ConstraintType GetConstraintType() const { return constraintType_; diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/ServerContext.cpp Tue Dec 18 18:56:55 2018 +0100 @@ -839,15 +839,16 @@ std::set r; for (size_t i = 0; i < resources2.size(); i++) { - r.insert(resources[i]); + r.insert(resources2[i]); } - assert(r.size() == resources.size()); + printf("%d %d\n", 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 fd587cf51a89 -r ea653ec47f31 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/ServerIndex.cpp Tue Dec 18 18:56:55 2018 +0100 @@ -2556,11 +2556,15 @@ } - void ServerIndex::NormalizeLookup(DatabaseLookup& target, + + void ServerIndex::NormalizeLookup(std::vector& target, const DatabaseLookup& source, ResourceType queryLevel) const { assert(mainDicomTagsRegistry_.get() != NULL); + + target.clear(); + target.reserve(source.GetConstraintsCount()); for (size_t i = 0; i < source.GetConstraintsCount(); i++) { @@ -2574,56 +2578,22 @@ (tagType == DicomTagType_Identifier || tagType == DicomTagType_Main)) { - if (tagType == DicomTagType_Identifier) + // Use the fact that patient-level tags are copied at the study level + if (queryLevel != ResourceType_Patient && + tagLevel == ResourceType_Patient) { - if (constraint.GetConstraintType() == ConstraintType_List) - { - if (!constraint.GetValues().empty()) - { - std::auto_ptr normalized( - new DicomTagConstraint(constraint.GetTag(), - ConstraintType_List, true, - constraint.IsMandatory())); - - normalized->SetTagType(tagType); - - for (std::set::const_iterator - value = constraint.GetValues().begin(); - value != constraint.GetValues().end(); ++value) - { - normalized->AddValue(ServerToolbox::NormalizeIdentifier(*value)); - } - - target.AddConstraint(normalized.release()); - } - } - else - { - std::string value = ServerToolbox::NormalizeIdentifier(constraint.GetValue()); - - std::auto_ptr normalized( - new DicomTagConstraint(constraint.GetTag(), - constraint.GetConstraintType(), - value, true, - constraint.IsMandatory())); - - normalized->SetTagType(tagType); - target.AddConstraint(normalized.release()); - } + tagLevel = ResourceType_Study; } - else if (tagType == DicomTagType_Main) + + DatabaseConstraint c(constraint, tagLevel, tagType); + + // Avoid universal constraints + if (!(c.GetConstraintType() == ConstraintType_Equal && + c.GetSingleValue() == "") && + !(c.GetConstraintType() == ConstraintType_Wildcard && + c.GetSingleValue() == "*")) { - std::auto_ptr clone(constraint.Clone()); - clone->SetTagType(tagType); - target.AddConstraint(clone.release()); - } - else if (tagType == DicomTagType_Generic) - { - // This tag is not indexed in the database, skip it - } - else - { - throw OrthancException(ErrorCode_InternalError); + target.push_back(c); } } } @@ -2635,7 +2605,7 @@ const DatabaseLookup& lookup, size_t limit) { - DatabaseLookup normalized; + std::vector normalized; NormalizeLookup(normalized, lookup, ResourceType_Patient); { @@ -2651,7 +2621,7 @@ ResourceType queryLevel, size_t limit) { - DatabaseLookup normalized; + std::vector normalized; NormalizeLookup(normalized, lookup, queryLevel); { diff -r fd587cf51a89 -r ea653ec47f31 OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Tue Dec 18 12:50:27 2018 +0100 +++ b/OrthancServer/ServerIndex.h Tue Dec 18 18:56:55 2018 +0100 @@ -127,7 +127,7 @@ MetadataType metadata, const std::string& value); - void NormalizeLookup(DatabaseLookup& target, + void NormalizeLookup(std::vector& target, const DatabaseLookup& source, ResourceType level) const; diff -r fd587cf51a89 -r ea653ec47f31 Plugins/Engine/OrthancPluginDatabase.cpp --- a/Plugins/Engine/OrthancPluginDatabase.cpp Tue Dec 18 12:50:27 2018 +0100 +++ b/Plugins/Engine/OrthancPluginDatabase.cpp Tue Dec 18 18:56:55 2018 +0100 @@ -1164,7 +1164,7 @@ void OrthancPluginDatabase::ApplyLookupPatients(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, size_t limit) { throw OrthancException(ErrorCode_NotImplemented); @@ -1173,7 +1173,7 @@ void OrthancPluginDatabase::ApplyLookupResources(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, ResourceType queryLevel, size_t limit) { diff -r fd587cf51a89 -r ea653ec47f31 Plugins/Engine/OrthancPluginDatabase.h --- a/Plugins/Engine/OrthancPluginDatabase.h Tue Dec 18 12:50:27 2018 +0100 +++ b/Plugins/Engine/OrthancPluginDatabase.h Tue Dec 18 18:56:55 2018 +0100 @@ -273,12 +273,12 @@ virtual void ApplyLookupPatients(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, size_t limit); virtual void ApplyLookupResources(std::vector& patientsId, std::vector& instancesId, - const DatabaseLookup& lookup, + const std::vector& lookup, ResourceType queryLevel, size_t limit); };