# HG changeset patch # User Sebastien Jodogne # Date 1547139852 -3600 # Node ID 1012fe77241c6a5c991779ce22150aef49437f17 # Parent 122f22550521051ee0b8b527697a85e9164bf050 new extension implemented for PostgreSQL and SQLite: GetLastChangeIndex diff -r 122f22550521 -r 1012fe77241c Framework/Plugins/IndexBackend.cpp --- a/Framework/Plugins/IndexBackend.cpp Thu Jan 10 13:33:33 2019 +0100 +++ b/Framework/Plugins/IndexBackend.cpp Thu Jan 10 18:04:12 2019 +0100 @@ -1862,7 +1862,6 @@ #endif -#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 // New primitive since Orthanc 1.5.2 void IndexBackend::GetChildrenMetadata(std::list& target, int64_t resourceId, @@ -1883,5 +1882,4 @@ ReadListOfStrings(target, statement, args); } -#endif } diff -r 122f22550521 -r 1012fe77241c Framework/Plugins/IndexBackend.h --- a/Framework/Plugins/IndexBackend.h Thu Jan 10 13:33:33 2019 +0100 +++ b/Framework/Plugins/IndexBackend.h Thu Jan 10 18:04:12 2019 +0100 @@ -277,11 +277,9 @@ const OrthancPluginResourcesContentMetadata* metadata); #endif -#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 // New primitive since Orthanc 1.5.2 virtual void GetChildrenMetadata(std::list& target, int64_t resourceId, int32_t metadata); -#endif }; } diff -r 122f22550521 -r 1012fe77241c Framework/Plugins/OrthancCppDatabasePlugin.h --- a/Framework/Plugins/OrthancCppDatabasePlugin.h Thu Jan 10 13:33:33 2019 +0100 +++ b/Framework/Plugins/OrthancCppDatabasePlugin.h Thu Jan 10 18:04:12 2019 +0100 @@ -492,7 +492,10 @@ virtual void ClearMainDicomTags(int64_t internalId) = 0; - virtual bool HasCreateInstance() const = 0; + virtual bool HasCreateInstance() const + { + return false; + } #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 virtual void LookupResources(const std::vector& lookup, @@ -524,11 +527,11 @@ #endif -#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 virtual void GetChildrenMetadata(std::list& target, int64_t resourceId, int32_t metadata) = 0; -#endif + + virtual int64_t GetLastChangeIndex() = 0; }; @@ -1585,8 +1588,6 @@ #endif - -#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 // New primitive since Orthanc 1.5.2 static OrthancPluginErrorCode GetChildrenMetadata(OrthancPluginDatabaseContext* context, void* payload, @@ -1613,8 +1614,23 @@ } ORTHANC_PLUGINS_DATABASE_CATCH } -#endif + + + // New primitive since Orthanc 1.5.2 + static OrthancPluginErrorCode GetLastChangeIndex(int64_t* result, + void* payload) + { + IDatabaseBackend* backend = reinterpret_cast(payload); + backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); + try + { + *result = backend->GetLastChangeIndex(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH + } + public: /** @@ -1700,6 +1716,7 @@ extensions.lookupResources = LookupResources; // Fast lookup extensions.setResourcesContent = SetResourcesContent; // Fast setting tags/metadata extensions.getChildrenMetadata = GetChildrenMetadata; + extensions.getLastChangeIndex = GetLastChangeIndex; if (backend.HasCreateInstance()) { diff -r 122f22550521 -r 1012fe77241c PostgreSQL/CMakeLists.txt --- a/PostgreSQL/CMakeLists.txt Thu Jan 10 13:33:33 2019 +0100 +++ b/PostgreSQL/CMakeLists.txt Thu Jan 10 18:04:12 2019 +0100 @@ -52,10 +52,11 @@ EmbedResources( - POSTGRESQL_PREPARE_INDEX ${CMAKE_SOURCE_DIR}/Plugins/PrepareIndex.sql - POSTGRESQL_CREATE_INSTANCE ${CMAKE_SOURCE_DIR}/Plugins/CreateInstance.sql - POSTGRESQL_FAST_TOTAL_SIZE ${CMAKE_SOURCE_DIR}/Plugins/FastTotalSize.sql - POSTGRESQL_FAST_COUNT_RESOURCES ${CMAKE_SOURCE_DIR}/Plugins/FastCountResources.sql + POSTGRESQL_PREPARE_INDEX ${CMAKE_SOURCE_DIR}/Plugins/PrepareIndex.sql + POSTGRESQL_CREATE_INSTANCE ${CMAKE_SOURCE_DIR}/Plugins/CreateInstance.sql + POSTGRESQL_FAST_TOTAL_SIZE ${CMAKE_SOURCE_DIR}/Plugins/FastTotalSize.sql + POSTGRESQL_FAST_COUNT_RESOURCES ${CMAKE_SOURCE_DIR}/Plugins/FastCountResources.sql + POSTGRESQL_GET_LAST_CHANGE_INDEX ${CMAKE_SOURCE_DIR}/Plugins/GetLastChangeIndex.sql ) add_library(OrthancPostgreSQLIndex SHARED diff -r 122f22550521 -r 1012fe77241c PostgreSQL/Plugins/GetLastChangeIndex.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PostgreSQL/Plugins/GetLastChangeIndex.sql Thu Jan 10 18:04:12 2019 +0100 @@ -0,0 +1,27 @@ +-- In PostgreSQL, the most straightforward query would be to run: + +-- SELECT currval(pg_get_serial_sequence('Changes', 'seq'))". + +-- Unfortunately, this raises the error message "currval of sequence +-- "changes_seq_seq" is not yet defined in this session" if no change +-- has been inserted before the SELECT. We thus track the sequence +-- index with a trigger. +-- http://www.neilconway.org/docs/sequences/ + +INSERT INTO GlobalIntegers +SELECT 6, CAST(COALESCE(MAX(seq), 0) AS BIGINT) FROM Changes; + + +CREATE FUNCTION InsertedChangeFunc() +RETURNS TRIGGER AS $body$ +BEGIN + UPDATE GlobalIntegers SET value = new.seq WHERE key = 6; + RETURN NULL; +END; +$body$ LANGUAGE plpgsql; + + +CREATE TRIGGER InsertedChange +AFTER INSERT ON Changes +FOR EACH ROW +EXECUTE PROCEDURE InsertedChangeFunc(); diff -r 122f22550521 -r 1012fe77241c PostgreSQL/Plugins/PostgreSQLIndex.cpp --- a/PostgreSQL/Plugins/PostgreSQLIndex.cpp Thu Jan 10 13:33:33 2019 +0100 +++ b/PostgreSQL/Plugins/PostgreSQLIndex.cpp Thu Jan 10 18:04:12 2019 +0100 @@ -37,6 +37,7 @@ static const GlobalProperty GlobalProperty_HasTrigramIndex = GlobalProperty_DatabaseInternal0; static const GlobalProperty GlobalProperty_HasCreateInstance = GlobalProperty_DatabaseInternal1; static const GlobalProperty GlobalProperty_HasFastCountResources = GlobalProperty_DatabaseInternal2; + static const GlobalProperty GlobalProperty_GetLastChangeIndex = GlobalProperty_DatabaseInternal3; } @@ -236,6 +237,29 @@ t.Commit(); } + { + PostgreSQLTransaction t(*db); + + // Installing this extension requires the "GlobalIntegers" table + // created by the "GetLastChangeIndex" extension + int property = 0; + if (!LookupGlobalIntegerProperty(property, *db, t, + Orthanc::GlobalProperty_GetLastChangeIndex) || + property != 1) + { + LOG(INFO) << "Installing the GetLastChangeIndex extension"; + + std::string query; + Orthanc::EmbeddedResources::GetFileResource + (query, Orthanc::EmbeddedResources::POSTGRESQL_GET_LAST_CHANGE_INDEX); + db->Execute(query); + + SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_GetLastChangeIndex, 1); + } + + t.Commit(); + } + return db.release(); } @@ -394,4 +418,17 @@ assert(result == IndexBackend::GetResourceCount(resourceType)); return result; } + + + int64_t PostgreSQLIndex::GetLastChangeIndex() + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT value FROM GlobalIntegers WHERE key = 6"); + + statement.SetReadOnly(true); + statement.Execute(); + + return ReadInteger64(statement, 0); + } } diff -r 122f22550521 -r 1012fe77241c PostgreSQL/Plugins/PostgreSQLIndex.h --- a/PostgreSQL/Plugins/PostgreSQLIndex.h Thu Jan 10 13:33:33 2019 +0100 +++ b/PostgreSQL/Plugins/PostgreSQLIndex.h Thu Jan 10 18:04:12 2019 +0100 @@ -94,5 +94,7 @@ virtual uint64_t GetResourceCount(OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE; + + virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE; }; } diff -r 122f22550521 -r 1012fe77241c SQLite/Plugins/SQLiteIndex.cpp --- a/SQLite/Plugins/SQLiteIndex.cpp Thu Jan 10 13:33:33 2019 +0100 +++ b/SQLite/Plugins/SQLiteIndex.cpp Thu Jan 10 18:04:12 2019 +0100 @@ -21,6 +21,7 @@ #include "SQLiteIndex.h" +#include "../../Framework/Common/Integer64Value.h" #include "../../Framework/Plugins/GlobalProperties.h" #include "../../Framework/SQLite/SQLiteDatabase.h" #include "../../Framework/SQLite/SQLiteTransaction.h" @@ -173,4 +174,35 @@ return dynamic_cast(statement.GetDatabase()).GetLastInsertRowId(); } + + + int64_t SQLiteIndex::GetLastChangeIndex() + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT seq FROM sqlite_sequence WHERE name='Changes'"); + + statement.SetReadOnly(true); + statement.Execute(); + + if (statement.IsDone()) + { + // No change has been recorded so far in the database + return 0; + } + else + { + const IValue& value = statement.GetResultField(0); + + switch (value.GetType()) + { + case ValueType_Integer64: + return dynamic_cast(value).GetValue(); + + default: + //LOG(ERROR) << value.Format(); + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + } } diff -r 122f22550521 -r 1012fe77241c SQLite/Plugins/SQLiteIndex.h --- a/SQLite/Plugins/SQLiteIndex.h Thu Jan 10 13:33:33 2019 +0100 +++ b/SQLite/Plugins/SQLiteIndex.h Thu Jan 10 18:04:12 2019 +0100 @@ -73,5 +73,8 @@ virtual int64_t CreateResource(const char* publicId, OrthancPluginResourceType type); + + // New primitive since Orthanc 1.5.2 + virtual int64_t GetLastChangeIndex(); }; }