# HG changeset patch # User Sebastien Jodogne # Date 1549293719 -3600 # Node ID c9eb54785de6b6437a4ba013aeb8642c0b93fc55 # Parent d4a995d2a726fcd845eaa3848ad1468990916e29# Parent ca0ecd4129888629d4da7e9e57687baff8022b21 integration OrthancMySQL-2.0 to mainline, to recover from commit in bad branch diff -r d4a995d2a726 -r c9eb54785de6 Framework/Common/DatabaseManager.cpp --- a/Framework/Common/DatabaseManager.cpp Wed Jan 23 20:14:41 2019 +0100 +++ b/Framework/Common/DatabaseManager.cpp Mon Feb 04 16:21:59 2019 +0100 @@ -21,6 +21,8 @@ #include "DatabaseManager.h" +#include + #include #include @@ -510,6 +512,18 @@ } assert(statement_ != NULL); + + /* + TODO - Sample code to monitor the execution time of each + cached statement, and publish it as an Orthanc metrics + + #if HAS_ORTHANC_PLUGIN_METRICS == 1 + std::string name = (std::string(location_.GetFile()) + "_" + + boost::lexical_cast(location_.GetLine())); + OrthancPlugins::MetricsTimer timer(name.c_str()); + #endif + */ + SetResult(GetTransaction().Execute(*statement_, parameters)); } catch (Orthanc::OrthancException& e) diff -r d4a995d2a726 -r c9eb54785de6 Framework/Plugins/IndexBackend.cpp --- a/Framework/Plugins/IndexBackend.cpp Wed Jan 23 20:14:41 2019 +0100 +++ b/Framework/Plugins/IndexBackend.cpp Mon Feb 04 16:21:59 2019 +0100 @@ -1739,9 +1739,9 @@ args.SetUtf8Value(name, tags[i].value); std::string insert = ("(" + boost::lexical_cast(tags[i].resource) + ", " + - boost::lexical_cast(tags[i].group) + ", " + - boost::lexical_cast(tags[i].element) + ", " + - "${" + name + "})"); + boost::lexical_cast(tags[i].group) + ", " + + boost::lexical_cast(tags[i].element) + ", " + + "${" + name + "})"); if (sql.empty()) { @@ -1787,7 +1787,7 @@ std::string insert = ("(" + boost::lexical_cast(metadata[i].resource) + ", " + boost::lexical_cast(metadata[i].metadata) + ", " + - "${" + name + "})"); + "${" + name + "})"); std::string remove = ("(id=" + boost::lexical_cast(metadata[i].resource) + " AND type=" + boost::lexical_cast(metadata[i].metadata) @@ -1951,4 +1951,108 @@ statement.Execute(args); } } + + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // New primitive since Orthanc 1.5.4 + bool IndexBackend::LookupResourceAndParent(int64_t& id, + OrthancPluginResourceType& type, + std::string& parentPublicId, + const char* publicId) + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, manager_, + "SELECT resource.internalId, resource.resourceType, parent.publicId " + "FROM Resources AS resource LEFT JOIN Resources parent ON parent.internalId=resource.parentId " + "WHERE resource.publicId=${id}"); + + statement.SetParameterType("id", ValueType_Utf8String); + + Dictionary args; + args.SetUtf8Value("id", publicId); + + statement.Execute(args); + + if (statement.IsDone()) + { + return false; + } + else + { + if (statement.GetResultFieldsCount() != 3) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + statement.SetResultFieldType(0, ValueType_Integer64); + statement.SetResultFieldType(1, ValueType_Integer64); + statement.SetResultFieldType(2, ValueType_Utf8String); + + id = ReadInteger64(statement, 0); + type = static_cast(ReadInteger32(statement, 1)); + + const IValue& value = statement.GetResultField(2); + + switch (value.GetType()) + { + case ValueType_Null: + parentPublicId.clear(); + break; + + case ValueType_Utf8String: + parentPublicId = dynamic_cast(value).GetContent(); + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + assert((statement.Next(), statement.IsDone())); + return true; + } + } +# endif +#endif + + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // New primitive since Orthanc 1.5.4 + void IndexBackend::GetAllMetadata(std::map& result, + int64_t id) + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, manager_, + "SELECT type, value FROM Metadata WHERE id=${id}"); + + statement.SetReadOnly(true); + statement.SetParameterType("id", ValueType_Integer64); + + Dictionary args; + args.SetIntegerValue("id", id); + + statement.Execute(args); + + result.clear(); + + if (!statement.IsDone()) + { + if (statement.GetResultFieldsCount() != 2) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + statement.SetResultFieldType(0, ValueType_Integer64); + statement.SetResultFieldType(1, ValueType_Utf8String); + + while (!statement.IsDone()) + { + result[ReadInteger32(statement, 0)] = ReadString(statement, 1); + statement.Next(); + } + } + } +# endif +#endif } diff -r d4a995d2a726 -r c9eb54785de6 Framework/Plugins/IndexBackend.h --- a/Framework/Plugins/IndexBackend.h Wed Jan 23 20:14:41 2019 +0100 +++ b/Framework/Plugins/IndexBackend.h Mon Feb 04 16:21:59 2019 +0100 @@ -283,5 +283,23 @@ int32_t metadata); virtual void TagMostRecentPatient(int64_t patient); + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // New primitive since Orthanc 1.5.4 + virtual bool LookupResourceAndParent(int64_t& id, + OrthancPluginResourceType& type, + std::string& parentPublicId, + const char* publicId); +# endif +#endif + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // New primitive since Orthanc 1.5.4 + virtual void GetAllMetadata(std::map& result, + int64_t id); +# endif +#endif }; } diff -r d4a995d2a726 -r c9eb54785de6 Framework/Plugins/OrthancCppDatabasePlugin.h --- a/Framework/Plugins/OrthancCppDatabasePlugin.h Wed Jan 23 20:14:41 2019 +0100 +++ b/Framework/Plugins/OrthancCppDatabasePlugin.h Mon Feb 04 16:21:59 2019 +0100 @@ -82,7 +82,8 @@ AllowedAnswers_DicomTag, AllowedAnswers_ExportedResource, AllowedAnswers_MatchingResource, - AllowedAnswers_String + AllowedAnswers_String, + AllowedAnswers_Metadata }; OrthancPluginContext* context_; @@ -534,6 +535,23 @@ virtual int64_t GetLastChangeIndex() = 0; virtual void TagMostRecentPatient(int64_t patientId) = 0; + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // NB: "parentPublicId" must be cleared if the resource has no parent + virtual bool LookupResourceAndParent(int64_t& id, + OrthancPluginResourceType& type, + std::string& parentPublicId, + const char* publicId) = 0; +# endif +#endif + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + virtual void GetAllMetadata(std::map& result, + int64_t id) = 0; +# endif +#endif }; @@ -1650,6 +1668,77 @@ } +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // New primitive since Orthanc 1.5.4 + static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseContext* context, + void* payload, + int64_t resourceId) + { + IDatabaseBackend* backend = reinterpret_cast(payload); + backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Metadata); + + try + { + std::map result; + backend->GetAllMetadata(result, resourceId); + + for (std::map::const_iterator + it = result.begin(); it != result.end(); ++it) + { + OrthancPluginDatabaseAnswerMetadata(backend->GetOutput().context_, + backend->GetOutput().database_, + resourceId, it->first, it->second.c_str()); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH + } +# endif +#endif + + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // New primitive since Orthanc 1.5.4 + static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseContext* context, + uint8_t* isExisting, + int64_t* id, + OrthancPluginResourceType* type, + void* payload, + const char* publicId) + { + IDatabaseBackend* backend = reinterpret_cast(payload); + backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_String); + + try + { + std::string parent; + if (backend->LookupResourceAndParent(*id, *type, parent, publicId)) + { + *isExisting = 1; + + if (!parent.empty()) + { + OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, + backend->GetOutput().database_, + parent.c_str()); + } + } + else + { + *isExisting = 0; + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH + } +# endif +#endif + + public: /** * Register a custom database back-end written in C++. @@ -1741,11 +1830,18 @@ { extensions.createInstance = CreateInstance; // Fast creation of resources } - - performanceWarning = false; #endif - if (performanceWarning) +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) + // Optimizations brought by Orthanc 1.5.4 + extensions.lookupResourceAndParent = LookupResourceAndParent; + extensions.getAllMetadata = GetAllMetadata; + performanceWarning = false; +# endif +#endif + + if (performanceWarning) { char info[1024]; sprintf(info, diff -r d4a995d2a726 -r c9eb54785de6 Framework/PostgreSQL/PostgreSQLTransaction.cpp --- a/Framework/PostgreSQL/PostgreSQLTransaction.cpp Wed Jan 23 20:14:41 2019 +0100 +++ b/Framework/PostgreSQL/PostgreSQLTransaction.cpp Mon Feb 04 16:21:59 2019 +0100 @@ -108,7 +108,7 @@ readOnly_ = false; } - return result.release(); + return result.release(); } diff -r d4a995d2a726 -r c9eb54785de6 MySQL/NEWS --- a/MySQL/NEWS Wed Jan 23 20:14:41 2019 +0100 +++ b/MySQL/NEWS Mon Feb 04 16:21:59 2019 +0100 @@ -1,6 +1,8 @@ Pending changes in the mainline =============================== +* Implementation of new extensions: LookupResourceAndParent and GetAllMetadata + Release 2.0 (2019-01-23) ======================== diff -r d4a995d2a726 -r c9eb54785de6 PostgreSQL/NEWS --- a/PostgreSQL/NEWS Wed Jan 23 20:14:41 2019 +0100 +++ b/PostgreSQL/NEWS Mon Feb 04 16:21:59 2019 +0100 @@ -3,6 +3,7 @@ * Fix build on Debian Buster * Remove "ASSERT" in SQL for compatibility with older releases of PostgreSQL +* Implementation of new extensions: LookupResourceAndParent and GetAllMetadata Release 3.0 (2019-01-21)