Mercurial > hg > orthanc-databases
diff Framework/Plugins/IndexBackend.cpp @ 70:e6c13ddd26d9 db-changes
all integration tests passing with LookupResources extension
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 03 Jan 2019 14:04:46 +0100 |
parents | 19764fc60ade |
children | a4e440e65c68 |
line wrap: on
line diff
--- a/Framework/Plugins/IndexBackend.cpp Thu Jan 03 10:07:27 2019 +0100 +++ b/Framework/Plugins/IndexBackend.cpp Thu Jan 03 14:04:46 2019 +0100 @@ -56,7 +56,7 @@ } - int64_t IndexBackend::ReadInteger64(const DatabaseManager::CachedStatement& statement, + int64_t IndexBackend::ReadInteger64(const DatabaseManager::StatementBase& statement, size_t field) { if (statement.IsDone()) @@ -78,7 +78,7 @@ } - int32_t IndexBackend::ReadInteger32(const DatabaseManager::CachedStatement& statement, + int32_t IndexBackend::ReadInteger32(const DatabaseManager::StatementBase& statement, size_t field) { if (statement.IsDone()) @@ -100,11 +100,11 @@ } - std::string IndexBackend::ReadString(const DatabaseManager::CachedStatement& statement, + std::string IndexBackend::ReadString(const DatabaseManager::StatementBase& statement, size_t field) { const IValue& value = statement.GetResultField(field); - + switch (value.GetType()) { case ValueType_BinaryString: @@ -1586,31 +1586,67 @@ class IndexBackend::LookupFormatter : public Orthanc::ISqlLookupFormatter { private: - Dialect dialect_; + Dialect dialect_; + size_t count_; + Dictionary dictionary_; + static std::string FormatParameter(size_t index) + { + return "p" + boost::lexical_cast<std::string>(index); + } + public: - LookupFormatter(Dialect dialect) : - dialect_(dialect) + LookupFormatter(Dialect dialect) : + dialect_(dialect), + count_(0) { } virtual std::string GenerateParameter(const std::string& value) { + const std::string key = FormatParameter(count_); + + count_ ++; + dictionary_.SetUtf8Value(key, value); + + return "${" + key + "}"; + } + + virtual std::string FormatResourceType(Orthanc::ResourceType level) + { + return boost::lexical_cast<std::string>(Orthanc::Plugins::Convert(level)); + } + + virtual std::string FormatWildcardEscape() + { switch (dialect_) { - case Dialect_MySQL: - break; - + case Dialect_SQLite: case Dialect_PostgreSQL: - break; + return "ESCAPE '\\'"; - case Dialect_SQLite: - break; + case Dialect_MySQL: + return "ESCAPE '\\\\'"; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } } + + void PrepareStatement(DatabaseManager::StandaloneStatement& statement) const + { + statement.SetReadOnly(true); + + for (size_t i = 0; i < count_; i++) + { + statement.SetParameterType(FormatParameter(i), ValueType_Utf8String); + } + } + + const Dictionary& GetDictionary() const + { + return dictionary_; + } }; #endif @@ -1622,13 +1658,65 @@ uint32_t limit, bool requestSomeInstance) { + LookupFormatter formatter(manager_.GetDialect()); + std::string sql; + Orthanc::ISqlLookupFormatter::Apply(sql, formatter, lookup, + Orthanc::Plugins::Convert(queryLevel), limit); + if (requestSomeInstance) { - LookupFormatter formatter(manager_.GetDialect()); - Orthanc::ISqlLookupFormatter::Apply(sql, formatter, lookup, - Orthanc::Plugins::Convert(queryLevel), limit); + // Composite query to find some instance if requested + switch (queryLevel) + { + case OrthancPluginResourceType_Patient: + sql = ("SELECT patients.publicId, MIN(instances.publicId) FROM (" + sql + ") patients " + "INNER JOIN Resources studies ON studies.parentId = patients.internalId " + "INNER JOIN Resources series ON series.parentId = studies.internalId " + "INNER JOIN Resources instances ON instances.parentId = series.internalId " + "GROUP BY patients.publicId"); + break; + + case OrthancPluginResourceType_Study: + sql = ("SELECT studies.publicId, MIN(instances.publicId) FROM (" + sql + ") studies " + "INNER JOIN Resources series ON series.parentId = studies.internalId " + "INNER JOIN Resources instances ON instances.parentId = series.internalId " + "GROUP BY studies.publicId"); + break; + + case OrthancPluginResourceType_Series: + sql = ("SELECT series.publicId, MIN(instances.publicId) FROM (" + sql + ") series " + "INNER JOIN Resources instances ON instances.parentId = series.internalId " + "GROUP BY series.publicId"); + break; + + case OrthancPluginResourceType_Instance: + sql = ("SELECT instances.publicId, instances.publicId FROM (" + sql + ") instances"); + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } } + + DatabaseManager::StandaloneStatement statement(GetManager(), sql); + formatter.PrepareStatement(statement); + + statement.Execute(formatter.GetDictionary()); + + while (!statement.IsDone()) + { + if (requestSomeInstance) + { + GetOutput().AnswerMatchingResource(ReadString(statement, 0), ReadString(statement, 1)); + } + else + { + GetOutput().AnswerMatchingResource(ReadString(statement, 0)); + } + + statement.Next(); + } } #endif }